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.js.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/backend_api.dart' show Backend; | |
9 import '../common/codegen.dart' show CodegenWorkItem; | 10 import '../common/codegen.dart' show CodegenWorkItem; |
11 import '../common/registry.dart' show Registry; | |
10 import '../common/names.dart' show Identifiers; | 12 import '../common/names.dart' show Identifiers; |
11 import '../common/resolution.dart' show Resolution; | |
12 import '../common/work.dart' show WorkItem; | 13 import '../common/work.dart' show WorkItem; |
13 import '../common.dart'; | 14 import '../common.dart'; |
14 import '../compiler.dart' show Compiler; | 15 import '../compiler.dart' show Compiler; |
15 import '../dart_types.dart' show DartType, InterfaceType; | 16 import '../dart_types.dart' show DartType, InterfaceType; |
16 import '../elements/elements.dart' | 17 import '../elements/elements.dart' |
17 show | 18 show |
18 ClassElement, | 19 ClassElement, |
19 ConstructorElement, | 20 ConstructorElement, |
20 Element, | 21 Element, |
21 Elements, | 22 Elements, |
22 Entity, | 23 Entity, |
23 FunctionElement, | 24 FunctionElement, |
24 LibraryElement, | 25 LibraryElement, |
25 Member, | 26 Member, |
26 MemberElement, | 27 MemberElement, |
27 Name, | 28 Name, |
28 TypedElement, | 29 TypedElement, |
29 TypedefElement; | 30 TypedefElement; |
30 import '../enqueue.dart'; | 31 import '../enqueue.dart'; |
31 import '../js/js.dart' as js; | 32 import '../js/js.dart' as js; |
32 import '../native/native.dart' as native; | 33 import '../native/native.dart' as native; |
34 import '../options.dart'; | |
33 import '../types/types.dart' show TypeMaskStrategy; | 35 import '../types/types.dart' show TypeMaskStrategy; |
34 import '../universe/selector.dart' show Selector; | 36 import '../universe/selector.dart' show Selector; |
35 import '../universe/universe.dart'; | 37 import '../universe/universe.dart'; |
36 import '../universe/use.dart' | 38 import '../universe/use.dart' |
37 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; | 39 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; |
38 import '../universe/world_impact.dart' | 40 import '../universe/world_impact.dart' |
39 show ImpactUseCase, WorldImpact, WorldImpactVisitor; | 41 show ImpactUseCase, WorldImpact, WorldImpactVisitor; |
40 import '../util/util.dart' show Setlet; | 42 import '../util/util.dart' show Setlet; |
43 import '../world.dart'; | |
41 | 44 |
42 /// [Enqueuer] which is specific to code generation. | 45 /// [Enqueuer] which is specific to code generation. |
43 class CodegenEnqueuer implements Enqueuer { | 46 class CodegenEnqueuer implements Enqueuer { |
44 final String name; | 47 final String name; |
45 final Compiler compiler; // TODO(ahe): Remove this dependency. | 48 @deprecated |
49 final Compiler _compiler; // TODO(ahe): Remove this dependency. | |
46 final EnqueuerStrategy strategy; | 50 final EnqueuerStrategy strategy; |
47 final Map<String, Set<Element>> instanceMembersByName = | 51 final Map<String, Set<Element>> instanceMembersByName = |
48 new Map<String, Set<Element>>(); | 52 new Map<String, Set<Element>>(); |
49 final Map<String, Set<Element>> instanceFunctionsByName = | 53 final Map<String, Set<Element>> instanceFunctionsByName = |
50 new Map<String, Set<Element>>(); | 54 new Map<String, Set<Element>>(); |
51 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); | 55 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); |
52 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); | 56 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); |
53 final Universe universe = new Universe(const TypeMaskStrategy()); | 57 final Universe universe = new Universe(const TypeMaskStrategy()); |
54 | 58 |
55 static final TRACE_MIRROR_ENQUEUING = | 59 static final TRACE_MIRROR_ENQUEUING = |
56 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); | 60 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); |
57 | 61 |
58 bool queueIsClosed = false; | 62 bool queueIsClosed = false; |
59 EnqueueTask task; | 63 EnqueueTask task; |
60 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask | 64 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask |
61 | 65 |
62 bool hasEnqueuedReflectiveElements = false; | 66 bool hasEnqueuedReflectiveElements = false; |
63 bool hasEnqueuedReflectiveStaticFields = false; | 67 bool hasEnqueuedReflectiveStaticFields = false; |
64 | 68 |
65 WorldImpactVisitor impactVisitor; | 69 WorldImpactVisitor impactVisitor; |
66 | 70 |
67 CodegenEnqueuer(Compiler compiler, this.strategy) | 71 CodegenEnqueuer(Compiler compiler, this.strategy) |
68 : queue = new Queue<CodegenWorkItem>(), | 72 : queue = new Queue<CodegenWorkItem>(), |
69 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), | 73 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), |
70 newlySeenSelectors = compiler.cacheStrategy.newSet(), | 74 newlySeenSelectors = compiler.cacheStrategy.newSet(), |
71 this.name = 'codegen enqueuer', | 75 this.name = 'codegen enqueuer', |
72 this.compiler = compiler { | 76 this._compiler = compiler { |
73 impactVisitor = new _EnqueuerImpactVisitor(this); | 77 impactVisitor = new _EnqueuerImpactVisitor(this); |
74 } | 78 } |
75 | 79 |
76 // TODO(johnniwinther): Move this to [ResolutionEnqueuer]. | 80 Backend get backend => _compiler.backend; |
77 Resolution get resolution => compiler.resolution; | 81 |
82 CompilerOptions get options => _compiler.options; | |
83 | |
84 Registry get globalDependencies => _compiler.globalDependencies; | |
85 | |
86 Registry get mirrorDependencies => _compiler.mirrorDependencies; | |
87 | |
88 ClassWorld get _world => _compiler.closedWorld; | |
78 | 89 |
79 bool get queueIsEmpty => queue.isEmpty; | 90 bool get queueIsEmpty => queue.isEmpty; |
80 | 91 |
81 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 92 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
82 bool get isResolutionQueue => false; | 93 bool get isResolutionQueue => false; |
83 | 94 |
84 QueueFilter get filter => compiler.enqueuerFilter; | 95 QueueFilter get filter => _compiler.enqueuerFilter; |
85 | 96 |
86 DiagnosticReporter get reporter => compiler.reporter; | 97 DiagnosticReporter get reporter => _compiler.reporter; |
87 | |
88 bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls); | |
89 | |
90 Iterable<ClassElement> get processedClasses => _processedClasses; | |
91 | 98 |
92 /** | 99 /** |
93 * Documentation wanted -- johnniwinther | 100 * Documentation wanted -- johnniwinther |
94 * | 101 * |
95 * Invariant: [element] must be a declaration element. | 102 * Invariant: [element] must be a declaration element. |
96 */ | 103 */ |
97 void addToWorkList(Element element) { | 104 void addToWorkList(Element element) { |
98 assert(invariant(element, element.isDeclaration)); | 105 assert(invariant(element, element.isDeclaration)); |
99 if (internalAddToWorkList(element) && compiler.options.dumpInfo) { | 106 // Don't generate code for foreign elements. |
107 if (backend.isForeign(element)) return; | |
108 | |
109 // Codegen inlines field initializers. It only needs to generate | |
110 // code for checked setters. | |
111 if (element.isField && element.isInstanceMember) { | |
112 if (!options.enableTypeAssertions || element.enclosingElement.isClosure) { | |
113 return; | |
114 } | |
115 } | |
116 | |
117 if (options.hasIncrementalSupport && !isProcessed(element)) { | |
118 newlyEnqueuedElements.add(element); | |
119 } | |
120 | |
121 if (queueIsClosed) { | |
122 throw new SpannableAssertionFailure( | |
123 element, "Codegen work list is closed. Trying to add $element"); | |
124 } | |
125 queue.add(new CodegenWorkItem(_compiler, element)); | |
126 if (options.dumpInfo) { | |
100 // TODO(sigmund): add other missing dependencies (internals, selectors | 127 // TODO(sigmund): add other missing dependencies (internals, selectors |
101 // enqueued after allocations), also enable only for the codegen enqueuer. | 128 // enqueued after allocations), also enable only for the codegen enqueuer. |
102 compiler.dumpInfoTask | 129 _compiler.dumpInfoTask |
103 .registerDependency(compiler.currentElement, element); | 130 .registerDependency(_compiler.currentElement, element); |
104 } | 131 } |
105 } | 132 } |
106 | 133 |
107 /// Apply the [worldImpact] of processing [element] to this enqueuer. | 134 /// Apply the [worldImpact] of processing [element] to this enqueuer. |
108 void applyImpact(Element element, WorldImpact worldImpact) { | 135 void applyImpact(Element element, WorldImpact worldImpact) { |
109 compiler.impactStrategy | 136 _compiler.impactStrategy |
110 .visitImpact(element, worldImpact, impactVisitor, impactUse); | 137 .visitImpact(element, worldImpact, impactVisitor, impactUse); |
111 } | 138 } |
112 | 139 |
113 void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false}) { | 140 void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false}) { |
114 task.measure(() { | 141 task.measure(() { |
115 ClassElement cls = type.element; | 142 ClassElement cls = type.element; |
116 cls.ensureResolved(resolution); | 143 bool isNative = backend.isNative(cls); |
117 bool isNative = compiler.backend.isNative(cls); | |
118 universe.registerTypeInstantiation(type, | 144 universe.registerTypeInstantiation(type, |
119 isNative: isNative, | 145 isNative: isNative, |
120 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { | 146 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { |
121 compiler.backend | 147 backend.registerImplementedClass(cls, this, globalDependencies); |
122 .registerImplementedClass(cls, this, compiler.globalDependencies); | |
123 }); | 148 }); |
124 // TODO(johnniwinther): Share this reasoning with [Universe]. | 149 // TODO(johnniwinther): Share this reasoning with [Universe]. |
125 if (!cls.isAbstract || isNative || mirrorUsage) { | 150 if (!cls.isAbstract || isNative || mirrorUsage) { |
126 processInstantiatedClass(cls); | 151 processInstantiatedClass(cls); |
127 } | 152 } |
128 }); | 153 }); |
129 } | 154 } |
130 | 155 |
131 bool checkNoEnqueuedInvokedInstanceMethods() { | 156 bool checkNoEnqueuedInvokedInstanceMethods() { |
132 return filter.checkNoEnqueuedInvokedInstanceMethods(this); | 157 return filter.checkNoEnqueuedInvokedInstanceMethods(this); |
(...skipping 10 matching lines...) Expand all Loading... | |
143 String memberName = member.name; | 168 String memberName = member.name; |
144 | 169 |
145 if (member.isField) { | 170 if (member.isField) { |
146 // The obvious thing to test here would be "member.isNative", | 171 // The obvious thing to test here would be "member.isNative", |
147 // however, that only works after metadata has been parsed/analyzed, | 172 // however, that only works after metadata has been parsed/analyzed, |
148 // and that may not have happened yet. | 173 // and that may not have happened yet. |
149 // So instead we use the enclosing class, which we know have had | 174 // So instead we use the enclosing class, which we know have had |
150 // its metadata parsed and analyzed. | 175 // its metadata parsed and analyzed. |
151 // Note: this assumes that there are no non-native fields on native | 176 // Note: this assumes that there are no non-native fields on native |
152 // classes, which may not be the case when a native class is subclassed. | 177 // classes, which may not be the case when a native class is subclassed. |
153 if (compiler.backend.isNative(cls)) { | 178 if (backend.isNative(cls)) { |
154 compiler.world.registerUsedElement(member); | 179 if (universe.hasInvokedGetter(member, _world) || |
155 if (universe.hasInvokedGetter(member, compiler.world) || | 180 universe.hasInvocation(member, _world)) { |
156 universe.hasInvocation(member, compiler.world)) { | |
157 addToWorkList(member); | 181 addToWorkList(member); |
158 return; | 182 return; |
159 } | 183 } |
160 if (universe.hasInvokedSetter(member, compiler.world)) { | 184 if (universe.hasInvokedSetter(member, _world)) { |
Harry Terkelsen
2016/09/19 17:18:26
nit: maybe this if-statement can be merged with th
Johnni Winther
2016/09/20 08:29:58
Done.
| |
161 addToWorkList(member); | 185 addToWorkList(member); |
162 return; | 186 return; |
163 } | 187 } |
164 // Native fields need to go into instanceMembersByName as they | 188 // Native fields need to go into instanceMembersByName as they |
165 // are virtual instantiation points and escape points. | 189 // are virtual instantiation points and escape points. |
166 } else { | 190 } else { |
167 // All field initializers must be resolved as they could | 191 // All field initializers must be resolved as they could |
168 // have an observable side-effect (and cannot be tree-shaken | 192 // have an observable side-effect (and cannot be tree-shaken |
169 // away). | 193 // away). |
170 addToWorkList(member); | 194 addToWorkList(member); |
171 return; | 195 return; |
172 } | 196 } |
173 } else if (member.isFunction) { | 197 } else if (member.isFunction) { |
174 FunctionElement function = member; | 198 FunctionElement function = member; |
175 function.computeType(resolution); | |
176 if (function.name == Identifiers.noSuchMethod_) { | 199 if (function.name == Identifiers.noSuchMethod_) { |
177 registerNoSuchMethod(function); | 200 registerNoSuchMethod(function); |
178 } | 201 } |
179 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { | 202 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { |
180 registerCallMethodWithFreeTypeVariables(function); | 203 registerCallMethodWithFreeTypeVariables(function); |
181 } | 204 } |
182 // If there is a property access with the same name as a method we | 205 // If there is a property access with the same name as a method we |
183 // need to emit the method. | 206 // need to emit the method. |
184 if (universe.hasInvokedGetter(function, compiler.world)) { | 207 if (universe.hasInvokedGetter(function, _world)) { |
185 registerClosurizedMember(function); | 208 registerClosurizedMember(function); |
186 addToWorkList(function); | 209 addToWorkList(function); |
187 return; | 210 return; |
188 } | 211 } |
189 // Store the member in [instanceFunctionsByName] to catch | 212 // Store the member in [instanceFunctionsByName] to catch |
190 // getters on the function. | 213 // getters on the function. |
191 instanceFunctionsByName | 214 instanceFunctionsByName |
192 .putIfAbsent(memberName, () => new Set<Element>()) | 215 .putIfAbsent(memberName, () => new Set<Element>()) |
193 .add(member); | 216 .add(member); |
194 if (universe.hasInvocation(function, compiler.world)) { | 217 if (universe.hasInvocation(function, _world)) { |
195 addToWorkList(function); | 218 addToWorkList(function); |
196 return; | 219 return; |
197 } | 220 } |
198 } else if (member.isGetter) { | 221 } else if (member.isGetter) { |
199 FunctionElement getter = member; | 222 FunctionElement getter = member; |
200 getter.computeType(resolution); | 223 if (universe.hasInvokedGetter(getter, _world)) { |
201 if (universe.hasInvokedGetter(getter, compiler.world)) { | |
202 addToWorkList(getter); | 224 addToWorkList(getter); |
203 return; | 225 return; |
204 } | 226 } |
205 // We don't know what selectors the returned closure accepts. If | 227 // We don't know what selectors the returned closure accepts. If |
206 // the set contains any selector we have to assume that it matches. | 228 // the set contains any selector we have to assume that it matches. |
207 if (universe.hasInvocation(getter, compiler.world)) { | 229 if (universe.hasInvocation(getter, _world)) { |
208 addToWorkList(getter); | 230 addToWorkList(getter); |
209 return; | 231 return; |
210 } | 232 } |
211 } else if (member.isSetter) { | 233 } else if (member.isSetter) { |
212 FunctionElement setter = member; | 234 FunctionElement setter = member; |
213 setter.computeType(resolution); | 235 if (universe.hasInvokedSetter(setter, _world)) { |
214 if (universe.hasInvokedSetter(setter, compiler.world)) { | |
215 addToWorkList(setter); | 236 addToWorkList(setter); |
216 return; | 237 return; |
217 } | 238 } |
218 } | 239 } |
219 | 240 |
220 // The element is not yet used. Add it to the list of instance | 241 // The element is not yet used. Add it to the list of instance |
221 // members to still be processed. | 242 // members to still be processed. |
222 instanceMembersByName | 243 instanceMembersByName |
223 .putIfAbsent(memberName, () => new Set<Element>()) | 244 .putIfAbsent(memberName, () => new Set<Element>()) |
224 .add(member); | 245 .add(member); |
225 } | 246 } |
226 | 247 |
227 void enableIsolateSupport() {} | 248 void enableIsolateSupport() {} |
228 | 249 |
229 void processInstantiatedClass(ClassElement cls) { | 250 void processInstantiatedClass(ClassElement cls) { |
230 task.measure(() { | 251 task.measure(() { |
231 if (_processedClasses.contains(cls)) return; | 252 if (_processedClasses.contains(cls)) return; |
232 // The class must be resolved to compute the set of all | |
233 // supertypes. | |
234 cls.ensureResolved(resolution); | |
235 | 253 |
236 void processClass(ClassElement superclass) { | 254 void processClass(ClassElement superclass) { |
237 if (_processedClasses.contains(superclass)) return; | 255 if (_processedClasses.contains(superclass)) return; |
238 // TODO(johnniwinther): Re-insert this invariant when unittests don't | 256 // TODO(johnniwinther): Re-insert this invariant when unittests don't |
239 // fail. There is already a similar invariant on the members. | 257 // fail. There is already a similar invariant on the members. |
240 /*if (!isResolutionQueue) { | 258 /*assert(invariant(superclass, |
241 assert(invariant(superclass, | |
242 superclass.isClosure || | 259 superclass.isClosure || |
243 compiler.enqueuer.resolution.isClassProcessed(superclass), | 260 _compiler.enqueuer.resolution.isClassProcessed(superclass), |
244 message: "Class $superclass has not been " | 261 message: "Class $superclass has not been " |
245 "processed in resolution.")); | 262 "processed in resolution.")); |
246 }*/ | 263 */ |
247 | 264 |
248 _processedClasses.add(superclass); | 265 _processedClasses.add(superclass); |
249 recentClasses.add(superclass); | 266 recentClasses.add(superclass); |
250 superclass.ensureResolved(resolution); | |
251 superclass.implementation.forEachMember(processInstantiatedClassMember); | 267 superclass.implementation.forEachMember(processInstantiatedClassMember); |
252 if (isResolutionQueue && | |
253 !compiler.serialization.isDeserialized(superclass)) { | |
254 compiler.resolver.checkClass(superclass); | |
255 } | |
256 // We only tell the backend once that [superclass] was instantiated, so | 268 // We only tell the backend once that [superclass] was instantiated, so |
257 // any additional dependencies must be treated as global | 269 // any additional dependencies must be treated as global |
258 // dependencies. | 270 // dependencies. |
259 compiler.backend.registerInstantiatedClass( | 271 backend.registerInstantiatedClass(superclass, this, globalDependencies); |
260 superclass, this, compiler.globalDependencies); | |
261 } | 272 } |
262 | 273 |
263 ClassElement superclass = cls; | 274 ClassElement superclass = cls; |
264 while (superclass != null) { | 275 while (superclass != null) { |
265 processClass(superclass); | 276 processClass(superclass); |
266 superclass = superclass.superclass; | 277 superclass = superclass.superclass; |
267 } | 278 } |
268 }); | 279 }); |
269 } | 280 } |
270 | 281 |
271 void registerDynamicUse(DynamicUse dynamicUse) { | 282 void registerDynamicUse(DynamicUse dynamicUse) { |
272 task.measure(() { | 283 task.measure(() { |
273 if (universe.registerDynamicUse(dynamicUse)) { | 284 if (universe.registerDynamicUse(dynamicUse)) { |
274 handleUnseenSelector(dynamicUse); | 285 handleUnseenSelector(dynamicUse); |
275 } | 286 } |
276 }); | 287 }); |
277 } | 288 } |
278 | 289 |
279 void logEnqueueReflectiveAction(action, [msg = ""]) { | 290 void logEnqueueReflectiveAction(action, [msg = ""]) { |
280 if (TRACE_MIRROR_ENQUEUING) { | 291 if (TRACE_MIRROR_ENQUEUING) { |
281 print("MIRROR_ENQUEUE (${isResolutionQueue ? "R" : "C"}): $action $msg"); | 292 print("MIRROR_ENQUEUE (C): $action $msg"); |
282 } | 293 } |
283 } | 294 } |
284 | 295 |
285 /// Enqeue the constructor [ctor] if it is required for reflection. | 296 /// Enqeue the constructor [ctor] if it is required for reflection. |
286 /// | 297 /// |
287 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 298 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
288 /// needed for reflection. | 299 /// needed for reflection. |
289 void enqueueReflectiveConstructor( | 300 void enqueueReflectiveConstructor( |
290 ConstructorElement ctor, bool enclosingWasIncluded) { | 301 ConstructorElement ctor, bool enclosingWasIncluded) { |
291 if (shouldIncludeElementDueToMirrors(ctor, | 302 if (shouldIncludeElementDueToMirrors(ctor, |
292 includedEnclosing: enclosingWasIncluded)) { | 303 includedEnclosing: enclosingWasIncluded)) { |
293 logEnqueueReflectiveAction(ctor); | 304 logEnqueueReflectiveAction(ctor); |
294 ClassElement cls = ctor.declaration.enclosingClass; | 305 ClassElement cls = ctor.declaration.enclosingClass; |
295 compiler.backend.registerInstantiatedType( | 306 backend.registerInstantiatedType(cls.rawType, this, mirrorDependencies, |
296 cls.rawType, this, compiler.mirrorDependencies, | |
297 mirrorUsage: true); | 307 mirrorUsage: true); |
298 registerStaticUse(new StaticUse.foreignUse(ctor.declaration)); | 308 registerStaticUse(new StaticUse.foreignUse(ctor.declaration)); |
299 } | 309 } |
300 } | 310 } |
301 | 311 |
302 /// Enqeue the member [element] if it is required for reflection. | 312 /// Enqeue the member [element] if it is required for reflection. |
303 /// | 313 /// |
304 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 314 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
305 /// needed for reflection. | 315 /// needed for reflection. |
306 void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) { | 316 void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) { |
307 if (shouldIncludeElementDueToMirrors(element, | 317 if (shouldIncludeElementDueToMirrors(element, |
308 includedEnclosing: enclosingWasIncluded)) { | 318 includedEnclosing: enclosingWasIncluded)) { |
309 logEnqueueReflectiveAction(element); | 319 logEnqueueReflectiveAction(element); |
310 if (element.isTypedef) { | 320 if (element.isTypedef) { |
311 TypedefElement typedef = element; | 321 // Do nothing. |
312 typedef.ensureResolved(resolution); | |
313 compiler.world.allTypedefs.add(element); | |
314 } else if (Elements.isStaticOrTopLevel(element)) { | 322 } else if (Elements.isStaticOrTopLevel(element)) { |
315 registerStaticUse(new StaticUse.foreignUse(element.declaration)); | 323 registerStaticUse(new StaticUse.foreignUse(element.declaration)); |
316 } else if (element.isInstanceMember) { | 324 } else if (element.isInstanceMember) { |
317 // We need to enqueue all members matching this one in subclasses, as | 325 // We need to enqueue all members matching this one in subclasses, as |
318 // well. | 326 // well. |
319 // TODO(herhut): Use TypedSelector.subtype for enqueueing | 327 // TODO(herhut): Use TypedSelector.subtype for enqueueing |
320 DynamicUse dynamicUse = | 328 DynamicUse dynamicUse = |
321 new DynamicUse(new Selector.fromElement(element), null); | 329 new DynamicUse(new Selector.fromElement(element), null); |
322 registerDynamicUse(dynamicUse); | 330 registerDynamicUse(dynamicUse); |
323 if (element.isField) { | 331 if (element.isField) { |
(...skipping 12 matching lines...) Expand all Loading... | |
336 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 344 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
337 /// needed for reflection. | 345 /// needed for reflection. |
338 void enqueueReflectiveElementsInClass(ClassElement cls, | 346 void enqueueReflectiveElementsInClass(ClassElement cls, |
339 Iterable<ClassElement> recents, bool enclosingWasIncluded) { | 347 Iterable<ClassElement> recents, bool enclosingWasIncluded) { |
340 if (cls.library.isInternalLibrary || cls.isInjected) return; | 348 if (cls.library.isInternalLibrary || cls.isInjected) return; |
341 bool includeClass = shouldIncludeElementDueToMirrors(cls, | 349 bool includeClass = shouldIncludeElementDueToMirrors(cls, |
342 includedEnclosing: enclosingWasIncluded); | 350 includedEnclosing: enclosingWasIncluded); |
343 if (includeClass) { | 351 if (includeClass) { |
344 logEnqueueReflectiveAction(cls, "register"); | 352 logEnqueueReflectiveAction(cls, "register"); |
345 ClassElement decl = cls.declaration; | 353 ClassElement decl = cls.declaration; |
346 decl.ensureResolved(resolution); | 354 backend.registerInstantiatedType(decl.rawType, this, mirrorDependencies, |
347 compiler.backend.registerInstantiatedType( | |
348 decl.rawType, this, compiler.mirrorDependencies, | |
349 mirrorUsage: true); | 355 mirrorUsage: true); |
350 } | 356 } |
351 // If the class is never instantiated, we know nothing of it can possibly | 357 // If the class is never instantiated, we know nothing of it can possibly |
352 // be reflected upon. | 358 // be reflected upon. |
353 // TODO(herhut): Add a warning if a mirrors annotation cannot hit. | 359 // TODO(herhut): Add a warning if a mirrors annotation cannot hit. |
354 if (recents.contains(cls.declaration)) { | 360 if (recents.contains(cls.declaration)) { |
355 logEnqueueReflectiveAction(cls, "members"); | 361 logEnqueueReflectiveAction(cls, "members"); |
356 cls.constructors.forEach((Element element) { | 362 cls.constructors.forEach((Element element) { |
357 enqueueReflectiveConstructor(element, includeClass); | 363 enqueueReflectiveConstructor(element, includeClass); |
358 }); | 364 }); |
359 cls.forEachClassMember((Member member) { | 365 cls.forEachClassMember((Member member) { |
360 enqueueReflectiveMember(member.element, includeClass); | 366 enqueueReflectiveMember(member.element, includeClass); |
361 }); | 367 }); |
362 } | 368 } |
363 } | 369 } |
364 | 370 |
365 /// Enqeue special classes that might not be visible by normal means or that | 371 /// Enqeue special classes that might not be visible by normal means or that |
366 /// would not normally be enqueued: | 372 /// would not normally be enqueued: |
367 /// | 373 /// |
368 /// [Closure] is treated specially as it is the superclass of all closures. | 374 /// [Closure] is treated specially as it is the superclass of all closures. |
369 /// Although it is in an internal library, we mark it as reflectable. Note | 375 /// Although it is in an internal library, we mark it as reflectable. Note |
370 /// that none of its methods are reflectable, unless reflectable by | 376 /// that none of its methods are reflectable, unless reflectable by |
371 /// inheritance. | 377 /// inheritance. |
372 void enqueueReflectiveSpecialClasses() { | 378 void enqueueReflectiveSpecialClasses() { |
373 Iterable<ClassElement> classes = | 379 Iterable<ClassElement> classes = backend.classesRequiredForReflection; |
374 compiler.backend.classesRequiredForReflection; | |
375 for (ClassElement cls in classes) { | 380 for (ClassElement cls in classes) { |
376 if (compiler.backend.referencedFromMirrorSystem(cls)) { | 381 if (backend.referencedFromMirrorSystem(cls)) { |
377 logEnqueueReflectiveAction(cls); | 382 logEnqueueReflectiveAction(cls); |
378 cls.ensureResolved(resolution); | 383 backend.registerInstantiatedType(cls.rawType, this, mirrorDependencies, |
379 compiler.backend.registerInstantiatedType( | |
380 cls.rawType, this, compiler.mirrorDependencies, | |
381 mirrorUsage: true); | 384 mirrorUsage: true); |
382 } | 385 } |
383 } | 386 } |
384 } | 387 } |
385 | 388 |
386 /// Enqeue all local members of the library [lib] if they are required for | 389 /// Enqeue all local members of the library [lib] if they are required for |
387 /// reflection. | 390 /// reflection. |
388 void enqueueReflectiveElementsInLibrary( | 391 void enqueueReflectiveElementsInLibrary( |
389 LibraryElement lib, Iterable<ClassElement> recents) { | 392 LibraryElement lib, Iterable<ClassElement> recents) { |
390 bool includeLibrary = | 393 bool includeLibrary = |
(...skipping 14 matching lines...) Expand all Loading... | |
405 if (!hasEnqueuedReflectiveElements) { | 408 if (!hasEnqueuedReflectiveElements) { |
406 logEnqueueReflectiveAction("!START enqueueAll"); | 409 logEnqueueReflectiveAction("!START enqueueAll"); |
407 // First round of enqueuing, visit everything that is visible to | 410 // First round of enqueuing, visit everything that is visible to |
408 // also pick up static top levels, etc. | 411 // also pick up static top levels, etc. |
409 // Also, during the first round, consider all classes that have been seen | 412 // Also, during the first round, consider all classes that have been seen |
410 // as recently seen, as we do not know how many rounds of resolution might | 413 // as recently seen, as we do not know how many rounds of resolution might |
411 // have run before tree shaking is disabled and thus everything is | 414 // have run before tree shaking is disabled and thus everything is |
412 // enqueued. | 415 // enqueued. |
413 recents = _processedClasses.toSet(); | 416 recents = _processedClasses.toSet(); |
414 reporter.log('Enqueuing everything'); | 417 reporter.log('Enqueuing everything'); |
415 for (LibraryElement lib in compiler.libraryLoader.libraries) { | 418 for (LibraryElement lib in _compiler.libraryLoader.libraries) { |
416 enqueueReflectiveElementsInLibrary(lib, recents); | 419 enqueueReflectiveElementsInLibrary(lib, recents); |
417 } | 420 } |
418 enqueueReflectiveSpecialClasses(); | 421 enqueueReflectiveSpecialClasses(); |
419 hasEnqueuedReflectiveElements = true; | 422 hasEnqueuedReflectiveElements = true; |
420 hasEnqueuedReflectiveStaticFields = true; | 423 hasEnqueuedReflectiveStaticFields = true; |
421 logEnqueueReflectiveAction("!DONE enqueueAll"); | 424 logEnqueueReflectiveAction("!DONE enqueueAll"); |
422 } else if (recents.isNotEmpty) { | 425 } else if (recents.isNotEmpty) { |
423 // Keep looking at new classes until fixpoint is reached. | 426 // Keep looking at new classes until fixpoint is reached. |
424 logEnqueueReflectiveAction("!START enqueueRecents"); | 427 logEnqueueReflectiveAction("!START enqueueRecents"); |
425 recents.forEach((ClassElement cls) { | 428 recents.forEach((ClassElement cls) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
467 } | 470 } |
468 | 471 |
469 void _handleUnseenSelector(DynamicUse universeSelector) { | 472 void _handleUnseenSelector(DynamicUse universeSelector) { |
470 strategy.processDynamicUse(this, universeSelector); | 473 strategy.processDynamicUse(this, universeSelector); |
471 } | 474 } |
472 | 475 |
473 void handleUnseenSelectorInternal(DynamicUse dynamicUse) { | 476 void handleUnseenSelectorInternal(DynamicUse dynamicUse) { |
474 Selector selector = dynamicUse.selector; | 477 Selector selector = dynamicUse.selector; |
475 String methodName = selector.name; | 478 String methodName = selector.name; |
476 processInstanceMembers(methodName, (Element member) { | 479 processInstanceMembers(methodName, (Element member) { |
477 if (dynamicUse.appliesUnnamed(member, compiler.world)) { | 480 if (dynamicUse.appliesUnnamed(member, _world)) { |
478 if (member.isFunction && selector.isGetter) { | 481 if (member.isFunction && selector.isGetter) { |
479 registerClosurizedMember(member); | 482 registerClosurizedMember(member); |
480 } | 483 } |
481 addToWorkList(member); | 484 addToWorkList(member); |
482 return true; | 485 return true; |
483 } | 486 } |
484 return false; | 487 return false; |
485 }); | 488 }); |
486 if (selector.isGetter) { | 489 if (selector.isGetter) { |
487 processInstanceFunctions(methodName, (Element member) { | 490 processInstanceFunctions(methodName, (Element member) { |
488 if (dynamicUse.appliesUnnamed(member, compiler.world)) { | 491 if (dynamicUse.appliesUnnamed(member, _world)) { |
489 registerClosurizedMember(member); | 492 registerClosurizedMember(member); |
490 return true; | 493 return true; |
491 } | 494 } |
492 return false; | 495 return false; |
493 }); | 496 }); |
494 } | 497 } |
495 } | 498 } |
496 | 499 |
497 /** | 500 /** |
498 * Documentation wanted -- johnniwinther | 501 * Documentation wanted -- johnniwinther |
499 * | 502 * |
500 * Invariant: [element] must be a declaration element. | 503 * Invariant: [element] must be a declaration element. |
501 */ | 504 */ |
502 void registerStaticUse(StaticUse staticUse) { | 505 void registerStaticUse(StaticUse staticUse) { |
503 strategy.processStaticUse(this, staticUse); | 506 strategy.processStaticUse(this, staticUse); |
504 } | 507 } |
505 | 508 |
506 void registerStaticUseInternal(StaticUse staticUse) { | 509 void registerStaticUseInternal(StaticUse staticUse) { |
507 Element element = staticUse.element; | 510 Element element = staticUse.element; |
508 assert(invariant(element, element.isDeclaration, | 511 assert(invariant(element, element.isDeclaration, |
509 message: "Element ${element} is not the declaration.")); | 512 message: "Element ${element} is not the declaration.")); |
510 universe.registerStaticUse(staticUse); | 513 universe.registerStaticUse(staticUse); |
511 compiler.backend.registerStaticUse(element, this); | 514 backend.registerStaticUse(element, this); |
512 bool addElement = true; | 515 bool addElement = true; |
513 switch (staticUse.kind) { | 516 switch (staticUse.kind) { |
514 case StaticUseKind.STATIC_TEAR_OFF: | 517 case StaticUseKind.STATIC_TEAR_OFF: |
515 compiler.backend.registerGetOfStaticFunction(this); | 518 backend.registerGetOfStaticFunction(this); |
516 break; | 519 break; |
517 case StaticUseKind.FIELD_GET: | 520 case StaticUseKind.FIELD_GET: |
518 case StaticUseKind.FIELD_SET: | 521 case StaticUseKind.FIELD_SET: |
519 case StaticUseKind.CLOSURE: | 522 case StaticUseKind.CLOSURE: |
520 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and | 523 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and |
521 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. | 524 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. |
522 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot | 525 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot |
523 // enqueue. | 526 // enqueue. |
524 addElement = false; | 527 addElement = false; |
525 break; | 528 break; |
(...skipping 13 matching lines...) Expand all Loading... | |
539 case TypeUseKind.INSTANTIATION: | 542 case TypeUseKind.INSTANTIATION: |
540 registerInstantiatedType(type); | 543 registerInstantiatedType(type); |
541 break; | 544 break; |
542 case TypeUseKind.INSTANTIATION: | 545 case TypeUseKind.INSTANTIATION: |
543 case TypeUseKind.IS_CHECK: | 546 case TypeUseKind.IS_CHECK: |
544 case TypeUseKind.AS_CAST: | 547 case TypeUseKind.AS_CAST: |
545 case TypeUseKind.CATCH_TYPE: | 548 case TypeUseKind.CATCH_TYPE: |
546 _registerIsCheck(type); | 549 _registerIsCheck(type); |
547 break; | 550 break; |
548 case TypeUseKind.CHECKED_MODE_CHECK: | 551 case TypeUseKind.CHECKED_MODE_CHECK: |
549 if (compiler.options.enableTypeAssertions) { | 552 if (options.enableTypeAssertions) { |
550 _registerIsCheck(type); | 553 _registerIsCheck(type); |
551 } | 554 } |
552 break; | 555 break; |
553 case TypeUseKind.TYPE_LITERAL: | 556 case TypeUseKind.TYPE_LITERAL: |
554 break; | 557 break; |
555 } | 558 } |
556 } | 559 } |
557 | 560 |
558 void _registerIsCheck(DartType type) { | 561 void _registerIsCheck(DartType type) { |
559 type = universe.registerIsCheck(type, compiler); | 562 type = universe.registerIsCheck(type, _compiler); |
560 // Even in checked mode, type annotations for return type and argument | 563 // Even in checked mode, type annotations for return type and argument |
561 // types do not imply type checks, so there should never be a check | 564 // types do not imply type checks, so there should never be a check |
562 // against the type variable of a typedef. | 565 // against the type variable of a typedef. |
563 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); | 566 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); |
564 } | 567 } |
565 | 568 |
566 void registerCallMethodWithFreeTypeVariables(Element element) { | 569 void registerCallMethodWithFreeTypeVariables(Element element) { |
567 compiler.backend.registerCallMethodWithFreeTypeVariables( | 570 backend.registerCallMethodWithFreeTypeVariables( |
568 element, this, compiler.globalDependencies); | 571 element, this, globalDependencies); |
569 universe.callMethodsWithFreeTypeVariables.add(element); | 572 universe.callMethodsWithFreeTypeVariables.add(element); |
570 } | 573 } |
571 | 574 |
572 void registerClosurizedMember(TypedElement element) { | 575 void registerClosurizedMember(TypedElement element) { |
573 assert(element.isInstanceMember); | 576 assert(element.isInstanceMember); |
574 if (element.computeType(resolution).containsTypeVariables) { | 577 if (element.type.containsTypeVariables) { |
575 compiler.backend.registerClosureWithFreeTypeVariables( | 578 backend.registerClosureWithFreeTypeVariables( |
576 element, this, compiler.globalDependencies); | 579 element, this, globalDependencies); |
577 } | 580 } |
578 compiler.backend.registerBoundClosure(this); | 581 backend.registerBoundClosure(this); |
579 universe.closurizedMembers.add(element); | 582 universe.closurizedMembers.add(element); |
580 } | 583 } |
581 | 584 |
582 void forEach(void f(WorkItem work)) { | 585 void forEach(void f(WorkItem work)) { |
583 do { | 586 do { |
584 while (queue.isNotEmpty) { | 587 while (queue.isNotEmpty) { |
585 // TODO(johnniwinther): Find an optimal process order. | 588 // TODO(johnniwinther): Find an optimal process order. |
586 filter.processWorkItem(f, queue.removeLast()); | 589 filter.processWorkItem(f, queue.removeLast()); |
587 } | 590 } |
588 List recents = recentClasses.toList(growable: false); | 591 List recents = recentClasses.toList(growable: false); |
589 recentClasses.clear(); | 592 recentClasses.clear(); |
590 if (!onQueueEmpty(recents)) recentClasses.addAll(recents); | 593 if (!onQueueEmpty(recents)) recentClasses.addAll(recents); |
591 } while (queue.isNotEmpty || recentClasses.isNotEmpty); | 594 } while (queue.isNotEmpty || recentClasses.isNotEmpty); |
592 } | 595 } |
593 | 596 |
594 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] | 597 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] |
595 /// contains the set of all classes seen for the first time since | 598 /// contains the set of all classes seen for the first time since |
596 /// [onQueueEmpty] was called last. A return value of [true] indicates that | 599 /// [onQueueEmpty] was called last. A return value of [true] indicates that |
597 /// the [recentClasses] have been processed and may be cleared. If [false] is | 600 /// the [recentClasses] have been processed and may be cleared. If [false] is |
598 /// returned, [onQueueEmpty] will be called once the queue is empty again (or | 601 /// returned, [onQueueEmpty] will be called once the queue is empty again (or |
599 /// still empty) and [recentClasses] will be a superset of the current value. | 602 /// still empty) and [recentClasses] will be a superset of the current value. |
600 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { | 603 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { |
601 return compiler.backend.onQueueEmpty(this, recentClasses); | 604 return backend.onQueueEmpty(this, recentClasses); |
602 } | 605 } |
603 | 606 |
604 void logSummary(log(message)) { | 607 void logSummary(log(message)) { |
605 _logSpecificSummary(log); | 608 _logSpecificSummary(log); |
606 nativeEnqueuer.logSummary(log); | 609 nativeEnqueuer.logSummary(log); |
607 } | 610 } |
608 | 611 |
609 String toString() => 'Enqueuer($name)'; | 612 String toString() => 'Enqueuer($name)'; |
610 | 613 |
611 void _forgetElement(Element element) { | 614 void _forgetElement(Element element) { |
612 universe.forgetElement(element, compiler); | 615 universe.forgetElement(element, _compiler); |
613 _processedClasses.remove(element); | 616 _processedClasses.remove(element); |
614 instanceMembersByName[element.name]?.remove(element); | 617 instanceMembersByName[element.name]?.remove(element); |
615 instanceFunctionsByName[element.name]?.remove(element); | 618 instanceFunctionsByName[element.name]?.remove(element); |
616 } | 619 } |
617 | 620 |
618 final Queue<CodegenWorkItem> queue; | 621 final Queue<CodegenWorkItem> queue; |
619 final Map<Element, js.Expression> generatedCode = <Element, js.Expression>{}; | 622 final Map<Element, js.Expression> generatedCode = <Element, js.Expression>{}; |
620 | 623 |
621 final Set<Element> newlyEnqueuedElements; | 624 final Set<Element> newlyEnqueuedElements; |
622 | 625 |
(...skipping 11 matching lines...) Expand all Loading... | |
634 | 637 |
635 /** | 638 /** |
636 * Decides whether an element should be included to satisfy requirements | 639 * Decides whether an element should be included to satisfy requirements |
637 * of the mirror system. | 640 * of the mirror system. |
638 * | 641 * |
639 * For code generation, we rely on the precomputed set of elements that takes | 642 * For code generation, we rely on the precomputed set of elements that takes |
640 * subtyping constraints into account. | 643 * subtyping constraints into account. |
641 */ | 644 */ |
642 bool shouldIncludeElementDueToMirrors(Element element, | 645 bool shouldIncludeElementDueToMirrors(Element element, |
643 {bool includedEnclosing}) { | 646 {bool includedEnclosing}) { |
644 return compiler.backend.isAccessibleByReflection(element); | 647 return backend.isAccessibleByReflection(element); |
645 } | |
646 | |
647 /** | |
648 * Adds [element] to the work list if it has not already been processed. | |
649 * | |
650 * Returns [true] if the element was actually added to the queue. | |
651 */ | |
652 bool internalAddToWorkList(Element element) { | |
653 // Don't generate code for foreign elements. | |
654 if (compiler.backend.isForeign(element)) return false; | |
655 | |
656 // Codegen inlines field initializers. It only needs to generate | |
657 // code for checked setters. | |
658 if (element.isField && element.isInstanceMember) { | |
659 if (!compiler.options.enableTypeAssertions || | |
660 element.enclosingElement.isClosure) { | |
661 return false; | |
662 } | |
663 } | |
664 | |
665 if (compiler.options.hasIncrementalSupport && !isProcessed(element)) { | |
666 newlyEnqueuedElements.add(element); | |
667 } | |
668 | |
669 if (queueIsClosed) { | |
670 throw new SpannableAssertionFailure( | |
671 element, "Codegen work list is closed. Trying to add $element"); | |
672 } | |
673 queue.add(new CodegenWorkItem(compiler, element)); | |
674 return true; | |
675 } | 648 } |
676 | 649 |
677 void registerNoSuchMethod(Element element) { | 650 void registerNoSuchMethod(Element element) { |
678 if (!enabledNoSuchMethod && compiler.backend.enabledNoSuchMethod) { | 651 if (!enabledNoSuchMethod && backend.enabledNoSuchMethod) { |
679 compiler.backend.enableNoSuchMethod(this); | 652 backend.enableNoSuchMethod(this); |
680 enabledNoSuchMethod = true; | 653 enabledNoSuchMethod = true; |
681 } | 654 } |
682 } | 655 } |
683 | 656 |
684 void _logSpecificSummary(log(message)) { | 657 void _logSpecificSummary(log(message)) { |
685 log('Compiled ${generatedCode.length} methods.'); | 658 log('Compiled ${generatedCode.length} methods.'); |
686 } | 659 } |
687 | 660 |
688 void forgetElement(Element element) { | 661 void forgetElement(Element element) { |
689 _forgetElement(element); | 662 _forgetElement(element); |
690 generatedCode.remove(element); | 663 generatedCode.remove(element); |
691 if (element is MemberElement) { | 664 if (element is MemberElement) { |
692 for (Element closure in element.nestedClosures) { | 665 for (Element closure in element.nestedClosures) { |
693 generatedCode.remove(closure); | 666 generatedCode.remove(closure); |
694 removeFromSet(instanceMembersByName, closure); | 667 removeFromSet(instanceMembersByName, closure); |
695 removeFromSet(instanceFunctionsByName, closure); | 668 removeFromSet(instanceFunctionsByName, closure); |
696 } | 669 } |
697 } | 670 } |
698 } | 671 } |
699 | 672 |
700 void handleUnseenSelector(DynamicUse dynamicUse) { | 673 void handleUnseenSelector(DynamicUse dynamicUse) { |
701 if (compiler.options.hasIncrementalSupport) { | 674 if (options.hasIncrementalSupport) { |
702 newlySeenSelectors.add(dynamicUse); | 675 newlySeenSelectors.add(dynamicUse); |
703 } | 676 } |
704 _handleUnseenSelector(dynamicUse); | 677 _handleUnseenSelector(dynamicUse); |
705 } | 678 } |
706 | 679 |
707 @override | 680 @override |
708 Iterable<Entity> get processedEntities => generatedCode.keys; | 681 Iterable<Entity> get processedEntities => generatedCode.keys; |
709 } | 682 } |
710 | 683 |
711 void removeFromSet(Map<String, Set<Element>> map, Element element) { | 684 void removeFromSet(Map<String, Set<Element>> map, Element element) { |
(...skipping 15 matching lines...) Expand all Loading... | |
727 @override | 700 @override |
728 void visitStaticUse(StaticUse staticUse) { | 701 void visitStaticUse(StaticUse staticUse) { |
729 enqueuer.registerStaticUse(staticUse); | 702 enqueuer.registerStaticUse(staticUse); |
730 } | 703 } |
731 | 704 |
732 @override | 705 @override |
733 void visitTypeUse(TypeUse typeUse) { | 706 void visitTypeUse(TypeUse typeUse) { |
734 enqueuer.registerTypeUse(typeUse); | 707 enqueuer.registerTypeUse(typeUse); |
735 } | 708 } |
736 } | 709 } |
OLD | NEW |