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

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

Issue 2488353004: Remove Compiler access from ResolutionEnqueuer (Closed)
Patch Set: Created 4 years, 1 month 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 'cache_strategy.dart';
10 import 'common/backend_api.dart' show Backend;
9 import 'common/names.dart' show Identifiers; 11 import 'common/names.dart' show Identifiers;
10 import 'common/resolution.dart' show Resolution; 12 import 'common/resolution.dart' show Resolution, ResolutionWorkItem;
11 import 'common/resolution.dart' show ResolutionWorkItem; 13 import 'common/registry.dart' show Registry;
12 import 'common/tasks.dart' show CompilerTask; 14 import 'common/tasks.dart' show CompilerTask;
13 import 'common/work.dart' show WorkItem; 15 import 'common/work.dart' show WorkItem;
14 import 'common.dart'; 16 import 'common.dart';
15 import 'compiler.dart' show Compiler; 17 import 'compiler.dart' show Compiler, GlobalDependencyRegistry;
18 import 'core_types.dart' show CommonElements;
19 import 'options.dart';
16 import 'dart_types.dart' show DartType, InterfaceType; 20 import 'dart_types.dart' show DartType, InterfaceType;
17 import 'elements/elements.dart' 21 import 'elements/elements.dart'
18 show 22 show
19 AnalyzableElement, 23 AnalyzableElement,
20 AstElement, 24 AstElement,
21 ClassElement, 25 ClassElement,
22 Element, 26 Element,
23 Entity, 27 Entity,
24 FunctionElement, 28 FunctionElement,
25 LibraryElement, 29 LibraryElement,
26 LocalFunctionElement, 30 LocalFunctionElement,
27 TypedElement; 31 TypedElement;
28 import 'native/native.dart' as native; 32 import 'native/native.dart' as native;
29 import 'types/types.dart' show TypeMaskStrategy; 33 import 'types/types.dart' show TypeMaskStrategy;
30 import 'universe/selector.dart' show Selector; 34 import 'universe/selector.dart' show Selector;
31 import 'universe/world_builder.dart'; 35 import 'universe/world_builder.dart';
32 import 'universe/use.dart' 36 import 'universe/use.dart'
33 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; 37 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind;
34 import 'universe/world_impact.dart' 38 import 'universe/world_impact.dart'
35 show ImpactUseCase, WorldImpact, WorldImpactVisitor; 39 show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor;
36 import 'util/util.dart' show Setlet; 40 import 'util/util.dart' show Setlet;
41 import 'world.dart' show OpenWorld;
37 42
38 class EnqueueTask extends CompilerTask { 43 class EnqueueTask extends CompilerTask {
39 final ResolutionEnqueuer resolution; 44 ResolutionEnqueuer _resolution;
40 final Enqueuer codegen; 45 Enqueuer _codegen;
41 final Compiler compiler; 46 final Compiler compiler;
42 47
43 String get name => 'Enqueue'; 48 String get name => 'Enqueue';
44 49
45 EnqueueTask(Compiler compiler) 50 EnqueueTask(Compiler compiler)
46 : compiler = compiler, 51 : this.compiler = compiler,
47 resolution = new ResolutionEnqueuer(
48 compiler,
49 compiler.options.analyzeOnly && compiler.options.analyzeMain
50 ? const EnqueuerStrategy()
51 : const TreeShakingEnqueuerStrategy()),
52 codegen = compiler.backend.createCodegenEnqueuer(compiler),
53 super(compiler.measurer) { 52 super(compiler.measurer) {
54 codegen.task = this; 53 _resolution = new ResolutionEnqueuer(
55 resolution.task = this; 54 this,
56 55 compiler.options,
57 codegen.nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(codegen); 56 compiler.resolution,
58 resolution.nativeEnqueuer = 57 compiler.enqueuerFilter,
59 compiler.backend.nativeResolutionEnqueuer(resolution); 58 compiler.options.analyzeOnly && compiler.options.analyzeMain
59 ? const EnqueuerStrategy()
60 : const TreeShakingEnqueuerStrategy(),
61 compiler.globalDependencies,
62 compiler.backend,
63 compiler.coreClasses,
64 compiler.cacheStrategy);
65 _codegen = compiler.backend.createCodegenEnqueuer(this, compiler);
60 } 66 }
61 67
68 ResolutionEnqueuer get resolution => _resolution;
69 Enqueuer get codegen => _codegen;
70
62 void forgetElement(Element element) { 71 void forgetElement(Element element) {
63 resolution.forgetElement(element); 72 resolution.forgetElement(element, compiler);
64 codegen.forgetElement(element); 73 codegen.forgetElement(element, compiler);
65 } 74 }
66 } 75 }
67 76
68 abstract class Enqueuer { 77 abstract class Enqueuer {
69 EnqueueTask task; 78 CompilerTask get task;
70 WorldBuilder get universe; 79 WorldBuilder get universe;
71 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask 80 native.NativeEnqueuer get nativeEnqueuer;
72 void forgetElement(Element element); 81 void forgetElement(Element element, Compiler compiler);
73 void processInstantiatedClassMembers(ClassElement cls); 82 void processInstantiatedClassMembers(ClassElement cls);
74 void processInstantiatedClassMember(ClassElement cls, Element member); 83 void processInstantiatedClassMember(ClassElement cls, Element member);
75 void handleUnseenSelectorInternal(DynamicUse dynamicUse); 84 void handleUnseenSelectorInternal(DynamicUse dynamicUse);
76 void registerStaticUse(StaticUse staticUse); 85 void registerStaticUse(StaticUse staticUse);
77 void registerStaticUseInternal(StaticUse staticUse); 86 void registerStaticUseInternal(StaticUse staticUse);
78 void registerDynamicUse(DynamicUse dynamicUse); 87 void registerDynamicUse(DynamicUse dynamicUse);
79 void registerTypeUse(TypeUse typeUse); 88 void registerTypeUse(TypeUse typeUse);
80 89
81 /// Returns [:true:] if this enqueuer is the resolution enqueuer. 90 /// Returns [:true:] if this enqueuer is the resolution enqueuer.
82 bool get isResolutionQueue; 91 bool get isResolutionQueue;
(...skipping 12 matching lines...) Expand all
95 void addToWorkList(Element element); 104 void addToWorkList(Element element);
96 105
97 void enableIsolateSupport(); 106 void enableIsolateSupport();
98 107
99 void registerInstantiatedType(InterfaceType type); 108 void registerInstantiatedType(InterfaceType type);
100 void forEach(void f(WorkItem work)); 109 void forEach(void f(WorkItem work));
101 110
102 /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is provide d 111 /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is provide d
103 /// the impact strategy will remove it from the element impact cache, if it is 112 /// the impact strategy will remove it from the element impact cache, if it is
104 /// no longer needed. 113 /// no longer needed.
105 void applyImpact(WorldImpact worldImpact, {Element impactSource}); 114 void applyImpact(ImpactStrategy impactStrategy, WorldImpact worldImpact,
115 {Element impactSource});
106 bool checkNoEnqueuedInvokedInstanceMethods(); 116 bool checkNoEnqueuedInvokedInstanceMethods();
107 void logSummary(log(message)); 117 void logSummary(log(message));
108 118
109 /// Returns [:true:] if [member] has been processed by this enqueuer. 119 /// Returns [:true:] if [member] has been processed by this enqueuer.
110 bool isProcessed(Element member); 120 bool isProcessed(Element member);
111 121
112 Iterable<Entity> get processedEntities; 122 Iterable<Entity> get processedEntities;
113 123
114 Iterable<ClassElement> get processedClasses; 124 Iterable<ClassElement> get processedClasses;
115 } 125 }
116 126
117 /// [Enqueuer] which is specific to resolution. 127 /// [Enqueuer] which is specific to resolution.
118 class ResolutionEnqueuer extends Enqueuer { 128 class ResolutionEnqueuer extends Enqueuer {
129 final CompilerTask task;
119 final String name; 130 final String name;
120 final Compiler compiler; // TODO(ahe): Remove this dependency. 131 final Resolution resolution;
132 final QueueFilter filter;
133 final CompilerOptions options;
134 final Backend backend;
135 final GlobalDependencyRegistry globalDependencies;
136 final CommonElements commonElements;
137 final native.NativeEnqueuer nativeEnqueuer;
138
121 final EnqueuerStrategy strategy; 139 final EnqueuerStrategy strategy;
122 final Map<String, Set<Element>> instanceMembersByName = 140 final Map<String, Set<Element>> instanceMembersByName =
123 new Map<String, Set<Element>>(); 141 new Map<String, Set<Element>>();
124 final Map<String, Set<Element>> instanceFunctionsByName = 142 final Map<String, Set<Element>> instanceFunctionsByName =
125 new Map<String, Set<Element>>(); 143 new Map<String, Set<Element>>();
126 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); 144 final Set<ClassElement> _processedClasses = new Set<ClassElement>();
127 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); 145 Set<ClassElement> recentClasses = new Setlet<ClassElement>();
128 final ResolutionWorldBuilderImpl _universe = 146 final ResolutionWorldBuilderImpl _universe;
129 new ResolutionWorldBuilderImpl(const TypeMaskStrategy());
130
131 147
132 bool queueIsClosed = false; 148 bool queueIsClosed = false;
133 149
134 WorldImpactVisitor impactVisitor; 150 WorldImpactVisitor impactVisitor;
135 151
136 ResolutionEnqueuer(Compiler compiler, this.strategy) 152 ImpactStrategy impactStrategy;
153
154 ResolutionEnqueuer(
155 this.task,
156 this.options,
157 Resolution resolution,
Harry Terkelsen 2016/11/11 22:07:30 you can just do 'this.resolution' here since you d
Johnni Winther 2016/11/14 09:16:06 Done.
158 this.filter,
159 this.strategy,
160 this.globalDependencies,
161 Backend backend,
162 CommonElements commonElements,
163 CacheStrategy cacheStrategy)
137 : this.name = 'resolution enqueuer', 164 : this.name = 'resolution enqueuer',
138 this.compiler = compiler, 165 this.backend = backend,
166 this.resolution = resolution,
167 this.commonElements = commonElements,
168 this.nativeEnqueuer = backend.nativeResolutionEnqueuer(),
139 processedElements = new Set<AstElement>(), 169 processedElements = new Set<AstElement>(),
140 queue = new Queue<ResolutionWorkItem>(), 170 queue = new Queue<ResolutionWorkItem>(),
141 deferredQueue = new Queue<_DeferredAction>() { 171 deferredQueue = new Queue<_DeferredAction>(),
172 _universe = new ResolutionWorldBuilderImpl(
173 backend, commonElements, cacheStrategy, const TypeMaskStrategy()) {
142 impactVisitor = new _EnqueuerImpactVisitor(this); 174 impactVisitor = new _EnqueuerImpactVisitor(this);
143 } 175 }
144 176
145 Resolution get resolution => compiler.resolution; 177 ResolutionWorldBuilder get universe => _universe;
146 178
147 ResolutionWorldBuilder get universe => _universe; 179 OpenWorld get openWorld => universe.openWorld;
148 180
149 bool get queueIsEmpty => queue.isEmpty; 181 bool get queueIsEmpty => queue.isEmpty;
150 182
151 QueueFilter get filter => compiler.enqueuerFilter; 183 DiagnosticReporter get reporter => resolution.reporter;
152
153 DiagnosticReporter get reporter => compiler.reporter;
154 184
155 bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls); 185 bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls);
156 186
157 Iterable<ClassElement> get processedClasses => _processedClasses; 187 Iterable<ClassElement> get processedClasses => _processedClasses;
158 188
159 /** 189 /**
160 * Documentation wanted -- johnniwinther 190 * Documentation wanted -- johnniwinther
161 * 191 *
162 * Invariant: [element] must be a declaration element. 192 * Invariant: [element] must be a declaration element.
163 */ 193 */
164 void addToWorkList(Element element) { 194 void addToWorkList(Element element) {
165 assert(invariant(element, element.isDeclaration)); 195 assert(invariant(element, element.isDeclaration));
166 if (internalAddToWorkList(element) && compiler.options.dumpInfo) { 196 internalAddToWorkList(element);
167 // TODO(sigmund): add other missing dependencies (internals, selectors 197 }
168 // enqueued after allocations), also enable only for the codegen enqueuer. 198
169 compiler.dumpInfoTask 199 void applyImpact(ImpactStrategy impactStrategy, WorldImpact worldImpact,
170 .registerDependency(compiler.currentElement, element); 200 {Element impactSource}) {
171 } 201 impactStrategy.visitImpact(
202 impactSource, worldImpact, impactVisitor, impactUse);
172 } 203 }
173 204
174 void registerInstantiatedType(InterfaceType type) { 205 void registerInstantiatedType(InterfaceType type) {
175 _registerInstantiatedType(type, globalDependency: true); 206 _registerInstantiatedType(type, globalDependency: true);
176 } 207 }
177 208
178 void applyImpact(WorldImpact worldImpact, {Element impactSource}) {
179 compiler.impactStrategy
180 .visitImpact(impactSource, worldImpact, impactVisitor, impactUse);
181 }
182
183 void _registerInstantiatedType(InterfaceType type, 209 void _registerInstantiatedType(InterfaceType type,
184 {bool mirrorUsage: false, 210 {bool mirrorUsage: false,
185 bool nativeUsage: false, 211 bool nativeUsage: false,
186 bool globalDependency: false}) { 212 bool globalDependency: false}) {
187 task.measure(() { 213 task.measure(() {
188 ClassElement cls = type.element; 214 ClassElement cls = type.element;
189 cls.ensureResolved(resolution); 215 cls.ensureResolved(resolution);
190 bool isNative = compiler.backend.isNative(cls); 216 bool isNative = backend.isNative(cls);
191 _universe.registerTypeInstantiation(type, 217 _universe.registerTypeInstantiation(type,
192 isNative: isNative, 218 isNative: isNative,
193 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { 219 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) {
194 compiler.backend.registerImplementedClass(cls, this); 220 backend.registerImplementedClass(cls, this);
195 }); 221 });
196 if (globalDependency && !mirrorUsage) { 222 if (globalDependency && !mirrorUsage) {
197 compiler.globalDependencies.registerDependency(type.element); 223 globalDependencies.registerDependency(type.element);
198 } 224 }
199 if (nativeUsage) { 225 if (nativeUsage) {
200 nativeEnqueuer.onInstantiatedType(type); 226 nativeEnqueuer.onInstantiatedType(type);
201 } 227 }
202 compiler.backend.registerInstantiatedType(type); 228 backend.registerInstantiatedType(type);
203 // TODO(johnniwinther): Share this reasoning with [Universe]. 229 // TODO(johnniwinther): Share this reasoning with [Universe].
204 if (!cls.isAbstract || isNative || mirrorUsage) { 230 if (!cls.isAbstract || isNative || mirrorUsage) {
205 processInstantiatedClass(cls); 231 processInstantiatedClass(cls);
206 } 232 }
207 }); 233 });
208 } 234 }
209 235
210 bool checkNoEnqueuedInvokedInstanceMethods() { 236 bool checkNoEnqueuedInvokedInstanceMethods() {
211 return filter.checkNoEnqueuedInvokedInstanceMethods(this); 237 return filter.checkNoEnqueuedInvokedInstanceMethods(this);
212 } 238 }
213 239
214 void processInstantiatedClassMembers(ClassElement cls) { 240 void processInstantiatedClassMembers(ClassElement cls) {
215 strategy.processInstantiatedClass(this, cls); 241 strategy.processInstantiatedClass(this, cls);
216 } 242 }
217 243
218 void processInstantiatedClassMember(ClassElement cls, Element member) { 244 void processInstantiatedClassMember(ClassElement cls, Element member) {
219 assert(invariant(member, member.isDeclaration)); 245 assert(invariant(member, member.isDeclaration));
220 if (isProcessed(member)) return; 246 if (isProcessed(member)) return;
221 if (!member.isInstanceMember) return; 247 if (!member.isInstanceMember) return;
222 String memberName = member.name; 248 String memberName = member.name;
223 249
224 if (member.isField) { 250 if (member.isField) {
225 // The obvious thing to test here would be "member.isNative", 251 // The obvious thing to test here would be "member.isNative",
226 // however, that only works after metadata has been parsed/analyzed, 252 // however, that only works after metadata has been parsed/analyzed,
227 // and that may not have happened yet. 253 // and that may not have happened yet.
228 // So instead we use the enclosing class, which we know have had 254 // So instead we use the enclosing class, which we know have had
229 // its metadata parsed and analyzed. 255 // its metadata parsed and analyzed.
230 // Note: this assumes that there are no non-native fields on native 256 // Note: this assumes that there are no non-native fields on native
231 // classes, which may not be the case when a native class is subclassed. 257 // classes, which may not be the case when a native class is subclassed.
232 if (compiler.backend.isNative(cls)) { 258 if (backend.isNative(cls)) {
233 compiler.openWorld.registerUsedElement(member); 259 openWorld.registerUsedElement(member);
234 if (_universe.hasInvokedGetter(member, compiler.openWorld) || 260 if (_universe.hasInvokedGetter(member, openWorld) ||
235 _universe.hasInvocation(member, compiler.openWorld)) { 261 _universe.hasInvocation(member, openWorld)) {
236 addToWorkList(member); 262 addToWorkList(member);
237 return; 263 return;
238 } 264 }
239 if (_universe.hasInvokedSetter(member, compiler.openWorld)) { 265 if (_universe.hasInvokedSetter(member, openWorld)) {
240 addToWorkList(member); 266 addToWorkList(member);
241 return; 267 return;
242 } 268 }
243 // Native fields need to go into instanceMembersByName as they 269 // Native fields need to go into instanceMembersByName as they
244 // are virtual instantiation points and escape points. 270 // are virtual instantiation points and escape points.
245 } else { 271 } else {
246 // All field initializers must be resolved as they could 272 // All field initializers must be resolved as they could
247 // have an observable side-effect (and cannot be tree-shaken 273 // have an observable side-effect (and cannot be tree-shaken
248 // away). 274 // away).
249 addToWorkList(member); 275 addToWorkList(member);
250 return; 276 return;
251 } 277 }
252 } else if (member.isFunction) { 278 } else if (member.isFunction) {
253 FunctionElement function = member; 279 FunctionElement function = member;
254 function.computeType(resolution); 280 function.computeType(resolution);
255 if (function.name == Identifiers.noSuchMethod_) { 281 if (function.name == Identifiers.noSuchMethod_) {
256 registerNoSuchMethod(function); 282 registerNoSuchMethod(function);
257 } 283 }
258 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { 284 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) {
259 registerCallMethodWithFreeTypeVariables(function); 285 registerCallMethodWithFreeTypeVariables(function);
260 } 286 }
261 // If there is a property access with the same name as a method we 287 // If there is a property access with the same name as a method we
262 // need to emit the method. 288 // need to emit the method.
263 if (_universe.hasInvokedGetter(function, compiler.openWorld)) { 289 if (_universe.hasInvokedGetter(function, openWorld)) {
264 registerClosurizedMember(function); 290 registerClosurizedMember(function);
265 addToWorkList(function); 291 addToWorkList(function);
266 return; 292 return;
267 } 293 }
268 // Store the member in [instanceFunctionsByName] to catch 294 // Store the member in [instanceFunctionsByName] to catch
269 // getters on the function. 295 // getters on the function.
270 instanceFunctionsByName 296 instanceFunctionsByName
271 .putIfAbsent(memberName, () => new Set<Element>()) 297 .putIfAbsent(memberName, () => new Set<Element>())
272 .add(member); 298 .add(member);
273 if (_universe.hasInvocation(function, compiler.openWorld)) { 299 if (_universe.hasInvocation(function, openWorld)) {
274 addToWorkList(function); 300 addToWorkList(function);
275 return; 301 return;
276 } 302 }
277 } else if (member.isGetter) { 303 } else if (member.isGetter) {
278 FunctionElement getter = member; 304 FunctionElement getter = member;
279 getter.computeType(resolution); 305 getter.computeType(resolution);
280 if (_universe.hasInvokedGetter(getter, compiler.openWorld)) { 306 if (_universe.hasInvokedGetter(getter, openWorld)) {
281 addToWorkList(getter); 307 addToWorkList(getter);
282 return; 308 return;
283 } 309 }
284 // We don't know what selectors the returned closure accepts. If 310 // We don't know what selectors the returned closure accepts. If
285 // the set contains any selector we have to assume that it matches. 311 // the set contains any selector we have to assume that it matches.
286 if (_universe.hasInvocation(getter, compiler.openWorld)) { 312 if (_universe.hasInvocation(getter, openWorld)) {
287 addToWorkList(getter); 313 addToWorkList(getter);
288 return; 314 return;
289 } 315 }
290 } else if (member.isSetter) { 316 } else if (member.isSetter) {
291 FunctionElement setter = member; 317 FunctionElement setter = member;
292 setter.computeType(resolution); 318 setter.computeType(resolution);
293 if (_universe.hasInvokedSetter(setter, compiler.openWorld)) { 319 if (_universe.hasInvokedSetter(setter, openWorld)) {
294 addToWorkList(setter); 320 addToWorkList(setter);
295 return; 321 return;
296 } 322 }
297 } 323 }
298 324
299 // The element is not yet used. Add it to the list of instance 325 // The element is not yet used. Add it to the list of instance
300 // members to still be processed. 326 // members to still be processed.
301 instanceMembersByName 327 instanceMembersByName
302 .putIfAbsent(memberName, () => new Set<Element>()) 328 .putIfAbsent(memberName, () => new Set<Element>())
303 .add(member); 329 .add(member);
304 } 330 }
305 331
306 void processInstantiatedClass(ClassElement cls) { 332 void processInstantiatedClass(ClassElement cls) {
307 task.measure(() { 333 task.measure(() {
308 if (_processedClasses.contains(cls)) return; 334 if (_processedClasses.contains(cls)) return;
309 // The class must be resolved to compute the set of all 335 // The class must be resolved to compute the set of all
310 // supertypes. 336 // supertypes.
311 cls.ensureResolved(resolution); 337 cls.ensureResolved(resolution);
312 338
313 void processClass(ClassElement superclass) { 339 void processClass(ClassElement superclass) {
314 if (_processedClasses.contains(superclass)) return; 340 if (_processedClasses.contains(superclass)) return;
315 341
316 _processedClasses.add(superclass); 342 _processedClasses.add(superclass);
317 recentClasses.add(superclass); 343 recentClasses.add(superclass);
318 superclass.ensureResolved(resolution); 344 superclass.ensureResolved(resolution);
319 superclass.implementation.forEachMember(processInstantiatedClassMember); 345 superclass.implementation.forEachMember(processInstantiatedClassMember);
320 if (!compiler.serialization.isDeserialized(superclass)) { 346 resolution.ensureClassMembers(superclass);
321 compiler.resolver.checkClass(superclass);
322 }
323 // We only tell the backend once that [superclass] was instantiated, so 347 // We only tell the backend once that [superclass] was instantiated, so
324 // any additional dependencies must be treated as global 348 // any additional dependencies must be treated as global
325 // dependencies. 349 // dependencies.
326 compiler.backend.registerInstantiatedClass(superclass, this); 350 backend.registerInstantiatedClass(superclass, this);
327 } 351 }
328 352
329 ClassElement superclass = cls; 353 ClassElement superclass = cls;
330 while (superclass != null) { 354 while (superclass != null) {
331 processClass(superclass); 355 processClass(superclass);
332 superclass = superclass.superclass; 356 superclass = superclass.superclass;
333 } 357 }
334 }); 358 });
335 } 359 }
336 360
(...skipping 29 matching lines...) Expand all
366 } 390 }
367 391
368 void handleUnseenSelector(DynamicUse universeSelector) { 392 void handleUnseenSelector(DynamicUse universeSelector) {
369 strategy.processDynamicUse(this, universeSelector); 393 strategy.processDynamicUse(this, universeSelector);
370 } 394 }
371 395
372 void handleUnseenSelectorInternal(DynamicUse dynamicUse) { 396 void handleUnseenSelectorInternal(DynamicUse dynamicUse) {
373 Selector selector = dynamicUse.selector; 397 Selector selector = dynamicUse.selector;
374 String methodName = selector.name; 398 String methodName = selector.name;
375 processInstanceMembers(methodName, (Element member) { 399 processInstanceMembers(methodName, (Element member) {
376 if (dynamicUse.appliesUnnamed(member, compiler.openWorld)) { 400 if (dynamicUse.appliesUnnamed(member, openWorld)) {
377 if (member.isFunction && selector.isGetter) { 401 if (member.isFunction && selector.isGetter) {
378 registerClosurizedMember(member); 402 registerClosurizedMember(member);
379 } 403 }
380 addToWorkList(member); 404 addToWorkList(member);
381 return true; 405 return true;
382 } 406 }
383 return false; 407 return false;
384 }); 408 });
385 if (selector.isGetter) { 409 if (selector.isGetter) {
386 processInstanceFunctions(methodName, (Element member) { 410 processInstanceFunctions(methodName, (Element member) {
387 if (dynamicUse.appliesUnnamed(member, compiler.openWorld)) { 411 if (dynamicUse.appliesUnnamed(member, openWorld)) {
388 registerClosurizedMember(member); 412 registerClosurizedMember(member);
389 return true; 413 return true;
390 } 414 }
391 return false; 415 return false;
392 }); 416 });
393 } 417 }
394 } 418 }
395 419
396 /** 420 /**
397 * Documentation wanted -- johnniwinther 421 * Documentation wanted -- johnniwinther
398 * 422 *
399 * Invariant: [element] must be a declaration element. 423 * Invariant: [element] must be a declaration element.
400 */ 424 */
401 void registerStaticUse(StaticUse staticUse) { 425 void registerStaticUse(StaticUse staticUse) {
402 strategy.processStaticUse(this, staticUse); 426 strategy.processStaticUse(this, staticUse);
403 } 427 }
404 428
405 void registerStaticUseInternal(StaticUse staticUse) { 429 void registerStaticUseInternal(StaticUse staticUse) {
406 Element element = staticUse.element; 430 Element element = staticUse.element;
407 assert(invariant(element, element.isDeclaration, 431 assert(invariant(element, element.isDeclaration,
408 message: "Element ${element} is not the declaration.")); 432 message: "Element ${element} is not the declaration."));
409 _universe.registerStaticUse(staticUse); 433 _universe.registerStaticUse(staticUse);
410 compiler.backend.registerStaticUse(this, element); 434 backend.registerStaticUse(this, element);
411 bool addElement = true; 435 bool addElement = true;
412 switch (staticUse.kind) { 436 switch (staticUse.kind) {
413 case StaticUseKind.STATIC_TEAR_OFF: 437 case StaticUseKind.STATIC_TEAR_OFF:
414 compiler.backend.registerGetOfStaticFunction(this); 438 backend.registerGetOfStaticFunction(this);
415 break; 439 break;
416 case StaticUseKind.FIELD_GET: 440 case StaticUseKind.FIELD_GET:
417 case StaticUseKind.FIELD_SET: 441 case StaticUseKind.FIELD_SET:
418 case StaticUseKind.CLOSURE: 442 case StaticUseKind.CLOSURE:
419 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and 443 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and
420 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. 444 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue.
421 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot 445 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot
422 // enqueue. 446 // enqueue.
423 LocalFunctionElement closure = staticUse.element; 447 LocalFunctionElement closure = staticUse.element;
424 if (closure.type.containsTypeVariables) { 448 if (closure.type.containsTypeVariables) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 case TypeUseKind.NATIVE_INSTANTIATION: 481 case TypeUseKind.NATIVE_INSTANTIATION:
458 _registerInstantiatedType(type, 482 _registerInstantiatedType(type,
459 nativeUsage: true, globalDependency: true); 483 nativeUsage: true, globalDependency: true);
460 break; 484 break;
461 case TypeUseKind.IS_CHECK: 485 case TypeUseKind.IS_CHECK:
462 case TypeUseKind.AS_CAST: 486 case TypeUseKind.AS_CAST:
463 case TypeUseKind.CATCH_TYPE: 487 case TypeUseKind.CATCH_TYPE:
464 _registerIsCheck(type); 488 _registerIsCheck(type);
465 break; 489 break;
466 case TypeUseKind.CHECKED_MODE_CHECK: 490 case TypeUseKind.CHECKED_MODE_CHECK:
467 if (compiler.options.enableTypeAssertions) { 491 if (options.enableTypeAssertions) {
468 _registerIsCheck(type); 492 _registerIsCheck(type);
469 } 493 }
470 break; 494 break;
471 case TypeUseKind.TYPE_LITERAL: 495 case TypeUseKind.TYPE_LITERAL:
472 break; 496 break;
473 } 497 }
474 } 498 }
475 499
476 void _registerIsCheck(DartType type) { 500 void _registerIsCheck(DartType type) {
477 type = _universe.registerIsCheck(type, compiler); 501 type = _universe.registerIsCheck(type, resolution);
478 // Even in checked mode, type annotations for return type and argument 502 // Even in checked mode, type annotations for return type and argument
479 // types do not imply type checks, so there should never be a check 503 // types do not imply type checks, so there should never be a check
480 // against the type variable of a typedef. 504 // against the type variable of a typedef.
481 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); 505 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef);
482 } 506 }
483 507
484 void registerCallMethodWithFreeTypeVariables(Element element) { 508 void registerCallMethodWithFreeTypeVariables(Element element) {
485 compiler.backend.registerCallMethodWithFreeTypeVariables(element, this); 509 backend.registerCallMethodWithFreeTypeVariables(element, this);
486 _universe.callMethodsWithFreeTypeVariables.add(element); 510 _universe.callMethodsWithFreeTypeVariables.add(element);
487 } 511 }
488 512
489 void registerClosurizedMember(TypedElement element) { 513 void registerClosurizedMember(TypedElement element) {
490 assert(element.isInstanceMember); 514 assert(element.isInstanceMember);
491 if (element.computeType(resolution).containsTypeVariables) { 515 if (element.computeType(resolution).containsTypeVariables) {
492 compiler.backend.registerClosureWithFreeTypeVariables(element, this); 516 backend.registerClosureWithFreeTypeVariables(element, this);
493 _universe.closuresWithFreeTypeVariables.add(element); 517 _universe.closuresWithFreeTypeVariables.add(element);
494 } 518 }
495 compiler.backend.registerBoundClosure(this); 519 backend.registerBoundClosure(this);
496 _universe.closurizedMembers.add(element); 520 _universe.closurizedMembers.add(element);
497 } 521 }
498 522
499 void forEach(void f(WorkItem work)) { 523 void forEach(void f(WorkItem work)) {
500 do { 524 do {
501 while (queue.isNotEmpty) { 525 while (queue.isNotEmpty) {
502 // TODO(johnniwinther): Find an optimal process order. 526 // TODO(johnniwinther): Find an optimal process order.
503 filter.processWorkItem(f, queue.removeLast()); 527 filter.processWorkItem(f, queue.removeLast());
504 } 528 }
505 List recents = recentClasses.toList(growable: false); 529 List recents = recentClasses.toList(growable: false);
(...skipping 30 matching lines...) Expand all
536 bool isProcessed(Element member) => processedElements.contains(member); 560 bool isProcessed(Element member) => processedElements.contains(member);
537 561
538 /// Returns `true` if [element] has been processed by the resolution enqueuer. 562 /// Returns `true` if [element] has been processed by the resolution enqueuer.
539 bool hasBeenProcessed(Element element) { 563 bool hasBeenProcessed(Element element) {
540 return processedElements.contains(element.analyzableElement.declaration); 564 return processedElements.contains(element.analyzableElement.declaration);
541 } 565 }
542 566
543 /// Registers [element] as processed by the resolution enqueuer. 567 /// Registers [element] as processed by the resolution enqueuer.
544 void registerProcessedElement(AstElement element) { 568 void registerProcessedElement(AstElement element) {
545 processedElements.add(element); 569 processedElements.add(element);
546 compiler.backend.onElementResolved(element); 570 backend.onElementResolved(element);
547 } 571 }
548 572
549 /** 573 /**
550 * Adds [element] to the work list if it has not already been processed. 574 * Adds [element] to the work list if it has not already been processed.
551 * 575 *
552 * Returns [true] if the element was actually added to the queue. 576 * Returns [true] if the element was actually added to the queue.
553 */ 577 */
554 bool internalAddToWorkList(Element element) { 578 bool internalAddToWorkList(Element element) {
555 if (element.isMalformed) return false; 579 if (element.isMalformed) return false;
556 580
557 assert(invariant(element, element is AnalyzableElement, 581 assert(invariant(element, element is AnalyzableElement,
558 message: 'Element $element is not analyzable.')); 582 message: 'Element $element is not analyzable.'));
559 if (hasBeenProcessed(element)) return false; 583 if (hasBeenProcessed(element)) return false;
560 if (queueIsClosed) { 584 if (queueIsClosed) {
561 throw new SpannableAssertionFailure( 585 throw new SpannableAssertionFailure(
562 element, "Resolution work list is closed. Trying to add $element."); 586 element, "Resolution work list is closed. Trying to add $element.");
563 } 587 }
564 588
565 compiler.openWorld.registerUsedElement(element); 589 openWorld.registerUsedElement(element);
566 590
567 ResolutionWorkItem workItem = compiler.resolution.createWorkItem(element); 591 ResolutionWorkItem workItem = resolution.createWorkItem(element);
568 queue.add(workItem); 592 queue.add(workItem);
569 593
570 // Enable isolate support if we start using something from the isolate 594 // Enable isolate support if we start using something from the isolate
571 // library, or timers for the async library. We exclude constant fields, 595 // library, or timers for the async library. We exclude constant fields,
572 // which are ending here because their initializing expression is compiled. 596 // which are ending here because their initializing expression is compiled.
573 LibraryElement library = element.library; 597 LibraryElement library = element.library;
574 if (!compiler.hasIsolateSupport && (!element.isField || !element.isConst)) { 598 if (!universe.hasIsolateSupport && (!element.isField || !element.isConst)) {
575 String uri = library.canonicalUri.toString(); 599 String uri = library.canonicalUri.toString();
576 if (uri == 'dart:isolate') { 600 if (uri == 'dart:isolate') {
577 enableIsolateSupport(); 601 enableIsolateSupport();
578 } else if (uri == 'dart:async') { 602 } else if (uri == 'dart:async') {
579 if (element.name == '_createTimer' || 603 if (element.name == '_createTimer' ||
580 element.name == '_createPeriodicTimer') { 604 element.name == '_createPeriodicTimer') {
581 // The [:Timer:] class uses the event queue of the isolate 605 // The [:Timer:] class uses the event queue of the isolate
582 // library, so we make sure that event queue is generated. 606 // library, so we make sure that event queue is generated.
583 enableIsolateSupport(); 607 enableIsolateSupport();
584 } 608 }
585 } 609 }
586 } 610 }
587 611
588 if (element.isGetter && element.name == Identifiers.runtimeType_) { 612 if (element.isGetter && element.name == Identifiers.runtimeType_) {
589 // Enable runtime type support if we discover a getter called runtimeType. 613 // Enable runtime type support if we discover a getter called runtimeType.
590 // We have to enable runtime type before hitting the codegen, so 614 // We have to enable runtime type before hitting the codegen, so
591 // that constructors know whether they need to generate code for 615 // that constructors know whether they need to generate code for
592 // runtime type. 616 // runtime type.
593 compiler.enabledRuntimeType = true; 617 _universe.hasRuntimeTypeSupport = true;
594 // TODO(ahe): Record precise dependency here. 618 // TODO(ahe): Record precise dependency here.
595 compiler.backend.registerRuntimeType(this); 619 backend.registerRuntimeType(this);
596 } else if (compiler.commonElements.isFunctionApplyMethod(element)) { 620 } else if (commonElements.isFunctionApplyMethod(element)) {
597 compiler.enabledFunctionApply = true; 621 _universe.hasFunctionApplySupport = true;
598 } 622 }
599 623
600 return true; 624 return true;
601 } 625 }
602 626
603 void registerNoSuchMethod(Element element) { 627 void registerNoSuchMethod(Element element) {
604 compiler.backend.registerNoSuchMethod(element); 628 backend.registerNoSuchMethod(element);
605 } 629 }
606 630
607 void enableIsolateSupport() { 631 void enableIsolateSupport() {
608 compiler.hasIsolateSupport = true; 632 _universe.hasIsolateSupport = true;
609 compiler.backend.enableIsolateSupport(this); 633 backend.enableIsolateSupport(this);
610 } 634 }
611 635
612 /** 636 /**
613 * Adds an action to the deferred task queue. 637 * Adds an action to the deferred task queue.
614 * 638 *
615 * The action is performed the next time the resolution queue has been 639 * The action is performed the next time the resolution queue has been
616 * emptied. 640 * emptied.
617 * 641 *
618 * The queue is processed in FIFO order. 642 * The queue is processed in FIFO order.
619 */ 643 */
620 void addDeferredAction(Element element, void action()) { 644 void addDeferredAction(Element element, void action()) {
621 if (queueIsClosed) { 645 if (queueIsClosed) {
622 throw new SpannableAssertionFailure( 646 throw new SpannableAssertionFailure(
623 element, 647 element,
624 "Resolution work list is closed. " 648 "Resolution work list is closed. "
625 "Trying to add deferred action for $element"); 649 "Trying to add deferred action for $element");
626 } 650 }
627 deferredQueue.add(new _DeferredAction(element, action)); 651 deferredQueue.add(new _DeferredAction(element, action));
628 } 652 }
629 653
630 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] 654 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses]
631 /// contains the set of all classes seen for the first time since 655 /// contains the set of all classes seen for the first time since
632 /// [onQueueEmpty] was called last. A return value of [true] indicates that 656 /// [onQueueEmpty] was called last. A return value of [true] indicates that
633 /// the [recentClasses] have been processed and may be cleared. If [false] is 657 /// the [recentClasses] have been processed and may be cleared. If [false] is
634 /// returned, [onQueueEmpty] will be called once the queue is empty again (or 658 /// returned, [onQueueEmpty] will be called once the queue is empty again (or
635 /// still empty) and [recentClasses] will be a superset of the current value. 659 /// still empty) and [recentClasses] will be a superset of the current value.
636 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { 660 bool onQueueEmpty(Iterable<ClassElement> recentClasses) {
637 _emptyDeferredQueue(); 661 _emptyDeferredQueue();
638 662
639 return compiler.backend.onQueueEmpty(this, recentClasses); 663 return backend.onQueueEmpty(this, recentClasses);
640 } 664 }
641 665
642 void emptyDeferredQueueForTesting() => _emptyDeferredQueue(); 666 void emptyDeferredQueueForTesting() => _emptyDeferredQueue();
643 667
644 void _emptyDeferredQueue() { 668 void _emptyDeferredQueue() {
645 while (!deferredQueue.isEmpty) { 669 while (!deferredQueue.isEmpty) {
646 _DeferredAction task = deferredQueue.removeFirst(); 670 _DeferredAction task = deferredQueue.removeFirst();
647 reporter.withCurrentElement(task.element, task.action); 671 reporter.withCurrentElement(task.element, task.action);
648 } 672 }
649 } 673 }
650 674
651 void forgetElement(Element element) { 675 void forgetElement(Element element, Compiler compiler) {
652 _universe.forgetElement(element, compiler); 676 _universe.forgetElement(element, compiler);
653 _processedClasses.remove(element); 677 _processedClasses.remove(element);
654 instanceMembersByName[element.name]?.remove(element); 678 instanceMembersByName[element.name]?.remove(element);
655 instanceFunctionsByName[element.name]?.remove(element); 679 instanceFunctionsByName[element.name]?.remove(element);
656 processedElements.remove(element); 680 processedElements.remove(element);
657 } 681 }
658 } 682 }
659 683
660 /// Parameterizes filtering of which work items are enqueued. 684 /// Parameterizes filtering of which work items are enqueued.
661 class QueueFilter { 685 class QueueFilter {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 } 765 }
742 766
743 typedef void _DeferredActionFunction(); 767 typedef void _DeferredActionFunction();
744 768
745 class _DeferredAction { 769 class _DeferredAction {
746 final Element element; 770 final Element element;
747 final _DeferredActionFunction action; 771 final _DeferredActionFunction action;
748 772
749 _DeferredAction(this.element, this.action); 773 _DeferredAction(this.element, this.action);
750 } 774 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698