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

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

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

Powered by Google App Engine
This is Rietveld 408576698