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 part of dart2js; | 5 part of dart2js; |
6 | 6 |
7 typedef ItemCompilationContext ItemCompilationContextCreator(); | 7 typedef ItemCompilationContext ItemCompilationContextCreator(); |
8 | 8 |
9 class EnqueueTask extends CompilerTask { | 9 class EnqueueTask extends CompilerTask { |
10 final ResolutionEnqueuer resolution; | 10 final ResolutionEnqueuer resolution; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 | 66 |
67 abstract class Enqueuer { | 67 abstract class Enqueuer { |
68 final String name; | 68 final String name; |
69 final Compiler compiler; // TODO(ahe): Remove this dependency. | 69 final Compiler compiler; // TODO(ahe): Remove this dependency. |
70 final ItemCompilationContextCreator itemCompilationContextCreator; | 70 final ItemCompilationContextCreator itemCompilationContextCreator; |
71 final Map<String, Link<Element>> instanceMembersByName | 71 final Map<String, Link<Element>> instanceMembersByName |
72 = new Map<String, Link<Element>>(); | 72 = new Map<String, Link<Element>>(); |
73 final Map<String, Link<Element>> instanceFunctionsByName | 73 final Map<String, Link<Element>> instanceFunctionsByName |
74 = new Map<String, Link<Element>>(); | 74 = new Map<String, Link<Element>>(); |
75 final Set<ClassElement> seenClasses = new Set<ClassElement>(); | 75 final Set<ClassElement> seenClasses = new Set<ClassElement>(); |
76 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); | |
76 final Universe universe = new Universe(); | 77 final Universe universe = new Universe(); |
77 | 78 |
79 static final TRACE_MIRROR_ENQUEUING = false; | |
floitsch
2014/06/27 08:59:15
should we start making these things const X.fromEn
herhut
2014/06/27 12:34:35
I did not know it was that easy to read an environ
| |
80 | |
78 bool queueIsClosed = false; | 81 bool queueIsClosed = false; |
79 EnqueueTask task; | 82 EnqueueTask task; |
80 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask | 83 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask |
81 | 84 |
82 bool hasEnqueuedEverything = false; | 85 bool hasEnqueuedReflectiveElements = false; |
83 bool hasEnqueuedReflectiveStaticFields = false; | 86 bool hasEnqueuedReflectiveStaticFields = false; |
84 | 87 |
85 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator); | 88 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator); |
86 | 89 |
87 Queue<WorkItem> get queue; | 90 Queue<WorkItem> get queue; |
88 bool get queueIsEmpty => queue.isEmpty; | 91 bool get queueIsEmpty => queue.isEmpty; |
89 | 92 |
90 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 93 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
91 bool get isResolutionQueue => false; | 94 bool get isResolutionQueue => false; |
92 | 95 |
93 /// Returns [:true:] if [member] has been processed by this enqueuer. | 96 /// Returns [:true:] if [member] has been processed by this enqueuer. |
94 bool isProcessed(Element member); | 97 bool isProcessed(Element member); |
95 | 98 |
96 /** | 99 /** |
97 * Documentation wanted -- johnniwinther | 100 * Documentation wanted -- johnniwinther |
98 * | 101 * |
99 * Invariant: [element] must be a declaration element. | 102 * Invariant: [element] must be a declaration element. |
100 */ | 103 */ |
101 void addToWorkList(Element element) { | 104 void addToWorkList(Element element) { |
102 assert(invariant(element, element.isDeclaration)); | 105 assert(invariant(element, element.isDeclaration)); |
103 internalAddToWorkList(element); | 106 internalAddToWorkList(element); |
104 } | 107 } |
105 | 108 |
106 /** | 109 /** |
107 * Adds [element] to the work list if it has not already been processed. | 110 * Adds [element] to the work list if it has not already been processed. |
108 */ | 111 */ |
109 void internalAddToWorkList(Element element); | 112 void internalAddToWorkList(Element element); |
110 | 113 |
111 void registerInstantiatedType(InterfaceType type, Registry registry) { | 114 void registerInstantiatedType(InterfaceType type, Registry registry, |
115 {mirrorUsage: false}) { | |
karlklose
2014/06/27 07:45:57
Only use registerInstantiatedType for types that a
herhut
2014/06/27 12:34:35
This only replicated what the original implementat
| |
112 task.measure(() { | 116 task.measure(() { |
113 ClassElement cls = type.element; | 117 ClassElement cls = type.element; |
114 registry.registerDependency(cls); | 118 registry.registerDependency(cls); |
115 cls.ensureResolved(compiler); | 119 cls.ensureResolved(compiler); |
116 universe.instantiatedTypes.add(type); | 120 universe.instantiatedTypes.add(type); |
117 if (!cls.isAbstract | 121 if (!cls.isAbstract |
118 // We can't use the closed-world assumption with native abstract | 122 // We can't use the closed-world assumption with native abstract |
119 // classes; a native abstract class may have non-abstract subclasses | 123 // classes; a native abstract class may have non-abstract subclasses |
120 // not declared to the program. Instances of these classes are | 124 // not declared to the program. Instances of these classes are |
121 // indistinguishable from the abstract class. | 125 // indistinguishable from the abstract class. |
122 || cls.isNative) { | 126 || cls.isNative |
127 // Likewise, if this registration comes from the mirror system, | |
128 // all bets are off. | |
129 || mirrorUsage) { | |
123 universe.instantiatedClasses.add(cls); | 130 universe.instantiatedClasses.add(cls); |
124 } | 131 } |
125 onRegisterInstantiatedClass(cls); | 132 onRegisterInstantiatedClass(cls); |
126 }); | 133 }); |
127 } | 134 } |
128 | 135 |
129 void registerInstantiatedClass(ClassElement cls, Registry registry) { | 136 void registerInstantiatedClass(ClassElement cls, Registry registry, |
137 {mirrorUsage: false}) { | |
130 cls.ensureResolved(compiler); | 138 cls.ensureResolved(compiler); |
131 registerInstantiatedType(cls.rawType, registry); | 139 registerInstantiatedType(cls.rawType, registry, mirrorUsage: mirrorUsage); |
132 } | 140 } |
133 | 141 |
134 bool checkNoEnqueuedInvokedInstanceMethods() { | 142 bool checkNoEnqueuedInvokedInstanceMethods() { |
135 task.measure(() { | 143 task.measure(() { |
136 // Run through the classes and see if we need to compile methods. | 144 // Run through the classes and see if we need to compile methods. |
137 for (ClassElement classElement in universe.instantiatedClasses) { | 145 for (ClassElement classElement in universe.instantiatedClasses) { |
138 for (ClassElement currentClass = classElement; | 146 for (ClassElement currentClass = classElement; |
139 currentClass != null; | 147 currentClass != null; |
140 currentClass = currentClass.superclass) { | 148 currentClass = currentClass.superclass) { |
141 processInstantiatedClass(currentClass); | 149 processInstantiatedClass(currentClass); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
253 task.measure(() { | 261 task.measure(() { |
254 if (seenClasses.contains(cls)) return; | 262 if (seenClasses.contains(cls)) return; |
255 // The class must be resolved to compute the set of all | 263 // The class must be resolved to compute the set of all |
256 // supertypes. | 264 // supertypes. |
257 cls.ensureResolved(compiler); | 265 cls.ensureResolved(compiler); |
258 | 266 |
259 void processClass(ClassElement cls) { | 267 void processClass(ClassElement cls) { |
260 if (seenClasses.contains(cls)) return; | 268 if (seenClasses.contains(cls)) return; |
261 | 269 |
262 seenClasses.add(cls); | 270 seenClasses.add(cls); |
271 recentClasses.add(cls); | |
263 cls.ensureResolved(compiler); | 272 cls.ensureResolved(compiler); |
264 cls.implementation.forEachMember(processInstantiatedClassMember); | 273 cls.implementation.forEachMember(processInstantiatedClassMember); |
265 if (isResolutionQueue) { | 274 if (isResolutionQueue) { |
266 compiler.resolver.checkClass(cls); | 275 compiler.resolver.checkClass(cls); |
267 } | 276 } |
268 // We only tell the backend once that [cls] was instantiated, so | 277 // We only tell the backend once that [cls] was instantiated, so |
269 // any additional dependencies must be treated as global | 278 // any additional dependencies must be treated as global |
270 // dependencies. | 279 // dependencies. |
271 compiler.backend.registerInstantiatedClass( | 280 compiler.backend.registerInstantiatedClass( |
272 cls, this, compiler.globalDependencies); | 281 cls, this, compiler.globalDependencies); |
(...skipping 28 matching lines...) Expand all Loading... | |
301 registerNewSelector(selector, universe.invokedGetters); | 310 registerNewSelector(selector, universe.invokedGetters); |
302 }); | 311 }); |
303 } | 312 } |
304 | 313 |
305 void registerInvokedSetter(Selector selector) { | 314 void registerInvokedSetter(Selector selector) { |
306 task.measure(() { | 315 task.measure(() { |
307 registerNewSelector(selector, universe.invokedSetters); | 316 registerNewSelector(selector, universe.invokedSetters); |
308 }); | 317 }); |
309 } | 318 } |
310 | 319 |
311 void pretendElementWasUsed(Element element, Registry registry) { | 320 /** |
312 if (!compiler.backend.isNeededForReflection(element)) return; | 321 * Decides whether an element should be included to satisfy requirements |
313 if (Elements.isUnresolved(element)) { | 322 * of the mirror system. |
314 // Ignore. | 323 * |
315 } else if (element.isSynthesized | 324 * The actual implementation depends on the current compiler phase. |
316 && element.library.isPlatformLibrary) { | 325 */ |
317 // TODO(ahe): Work-around for http://dartbug.com/11205. | 326 bool includeElementDueToMirrors(bool includeEnclosing, Element element); |
Johnni Winther
2014/06/27 07:43:01
Rename to [shouldIncludeElementDueToMirror] to ind
Johnni Winther
2014/06/27 07:43:01
Make [includeEnclosing] a named parameter.
herhut
2014/06/27 12:34:36
Done.
herhut
2014/06/27 12:34:36
Done.
| |
318 } else if (element.isConstructor) { | 327 |
319 ClassElement cls = element.declaration.enclosingClass; | 328 void logEnqueueReflectiveAction(action, [msg = ""]) { |
320 registerInstantiatedType(cls.rawType, registry); | 329 if (TRACE_MIRROR_ENQUEUING) { |
321 registerStaticUse(element.declaration); | 330 print("MIRROR_ENQUEUE (${isResolutionQueue ? "R" : "B"}): $action $msg"); |
karlklose
2014/06/27 07:45:57
'R' -> 'resolution'?
What is 'B'?
herhut
2014/06/27 12:34:36
Backend. Probably C for codegen is better. I have
| |
322 } else if (element.isClass) { | 331 } |
323 ClassElement cls = element.declaration; | 332 } |
324 registerInstantiatedClass(cls, registry); | 333 |
325 // Make sure that even abstract classes are considered instantiated. | 334 void enqueueReflectiveConstructor(ConstructorElement ctor, bool add) { |
Johnni Winther
2014/06/27 07:43:00
Add comment. I guess it is a helper method for [en
Johnni Winther
2014/06/27 07:43:01
Make [add] named.
karlklose
2014/06/27 07:45:57
Could you add a comment about the semantics of 'ad
floitsch
2014/06/27 08:59:15
nit: s/add/forceAdd/
I'm guessing that's the mean
herhut
2014/06/27 12:34:36
Done.
herhut
2014/06/27 12:34:36
Done.
herhut
2014/06/27 12:34:36
Done.
herhut
2014/06/27 12:34:37
Done.
| |
326 universe.instantiatedClasses.add(cls); | 335 if (includeElementDueToMirrors(add, ctor)) { |
327 } else if (element.impliesType) { | 336 logEnqueueReflectiveAction(ctor); |
328 // Don't enqueue typedefs, and type variables. | 337 ClassElement cls = ctor.declaration.enclosingClass; |
329 } else if (Elements.isStaticOrTopLevel(element)) { | 338 registerInstantiatedType(cls.rawType, compiler.mirrorDependencies); |
Johnni Winther
2014/06/27 07:43:01
Shouldn't this call have `mirrorUsage: true` ?
karlklose
2014/06/27 07:45:57
I am not sure we should register this type here.
herhut
2014/06/27 12:34:35
It will not have an effect currently but it is mor
herhut
2014/06/27 12:34:36
This implements what was done before. I will redo
| |
330 registerStaticUse(element.declaration); | 339 registerStaticUse(ctor.declaration); |
331 } else if (element.isInstanceMember) { | 340 } |
332 Selector selector = new Selector.fromElement(element, compiler); | 341 } |
333 registerSelectorUse(selector); | 342 |
334 if (element.isField) { | 343 void enqueueReflectiveMember(Element element, bool add) { |
Johnni Winther
2014/06/27 07:43:00
Make [add] named.
Johnni Winther
2014/06/27 07:43:01
Add comment.
herhut
2014/06/27 12:34:35
Done.
herhut
2014/06/27 12:34:36
Done.
| |
335 Selector selector = | 344 add = includeElementDueToMirrors(add, element); |
karlklose
2014/06/27 07:45:57
Inline call to includeElementsDueToMirrors? (Also
herhut
2014/06/27 12:34:36
Below I have to pass the result on to the processi
| |
336 new Selector.setter(element.name, element.library); | 345 if (add && !element.impliesType) { |
floitsch
2014/06/27 08:59:15
Keep comment exlpaining what "impliesType" means.
herhut
2014/06/27 12:34:36
Done.
| |
337 registerInvokedSetter(selector); | 346 logEnqueueReflectiveAction(element); |
347 if (Elements.isStaticOrTopLevel(element)) { | |
348 registerStaticUse(element.declaration); | |
349 } else if (element.isInstanceMember) { | |
350 // We need to enqueue all members matching this one in subclasses, as | |
351 // well. | |
352 // TODO(herhut): Use TypedSelector.subtype for enqueueing | |
353 Selector selector = new Selector.fromElement(element, compiler); | |
354 registerSelectorUse(selector); | |
355 if (element.isField) { | |
356 Selector selector = | |
357 new Selector.setter(element.name, element.library); | |
358 registerInvokedSetter(selector); | |
359 } | |
338 } | 360 } |
339 } | 361 } |
340 } | 362 } |
341 | 363 |
342 void enqueueEverything() { | 364 void enqueueReflectiveElementsInClass(ClassElement cls, |
Johnni Winther
2014/06/27 07:43:00
Add comment.
herhut
2014/06/27 12:34:36
Done.
| |
343 if (hasEnqueuedEverything) return; | 365 Iterable<ClassElement> recents, |
344 compiler.log('Enqueuing everything'); | 366 bool add) { |
Johnni Winther
2014/06/27 07:43:00
Make [add] named.
herhut
2014/06/27 12:34:37
Done.
| |
345 task.ensureAllElementsByName(); | 367 if (cls.library.isInternalLibrary) return; |
346 for (Link link in task.allElementsByName.values) { | 368 if (cls.isInjected) return; |
Johnni Winther
2014/06/27 07:43:00
Merge conditions.
herhut
2014/06/27 12:34:36
Done.
| |
347 for (Element element in link) { | 369 add = includeElementDueToMirrors(add, cls); |
348 pretendElementWasUsed(element, compiler.mirrorDependencies); | 370 if (add) { |
371 logEnqueueReflectiveAction(cls, "register"); | |
372 ClassElement decl = cls.declaration; | |
373 registerInstantiatedClass(decl, compiler.mirrorDependencies, | |
374 mirrorUsage: true); | |
375 } | |
376 // If the class is never instantiated, we know nothing of it can possibly | |
377 // be reflected upon. | |
378 // TODO(herhut): Add a warning if a mirrors annotation cannot hit. | |
379 if (recents.contains(cls.declaration)) { | |
380 logEnqueueReflectiveAction(cls, "members"); | |
381 cls.constructors.forEach((Element element) { | |
382 enqueueReflectiveConstructor(element, add); | |
383 }); | |
384 cls.forEachClassMember((Member member) { | |
385 enqueueReflectiveMember(member.element, add); | |
386 }); | |
387 } | |
388 } | |
389 | |
390 void enqueueReflectiveSpecialClasses() { | |
Johnni Winther
2014/06/27 07:43:00
Add comment.
herhut
2014/06/27 12:34:36
Done.
| |
391 // [Closure] is treated specially as it is the superclass of all closures. | |
392 // Although it is in an internal library, we mark it as reflectable. Note | |
393 // that none of its methods are reflectable, unless reflectable by | |
394 // inheritance. | |
395 ClassElement closureClass = compiler.closureClass; | |
396 if (compiler.backend.referencedFromMirrorSystem(closureClass)) { | |
397 logEnqueueReflectiveAction(closureClass); | |
398 registerInstantiatedClass(closureClass, compiler.mirrorDependencies, | |
399 mirrorUsage: true); | |
400 } | |
401 } | |
402 | |
403 void enqueueReflectiveElementsInLibrary(LibraryElement lib, | |
Johnni Winther
2014/06/27 07:43:00
Add comment.
herhut
2014/06/27 12:34:36
Done.
| |
404 Iterable<ClassElement> recents, | |
405 bool add) { | |
406 add = includeElementDueToMirrors(add, lib); | |
407 lib.forEachLocalMember((Element member) { | |
408 if (member.isClass) { | |
409 enqueueReflectiveElementsInClass(member, recents, add); | |
410 } else { | |
411 enqueueReflectiveMember(member, add); | |
349 } | 412 } |
413 }); | |
414 } | |
415 | |
416 /// Enqueue all elements that are matched by the mirrors used | |
417 /// annotation or, in lack thereof, all elements. | |
418 void enqueueReflectiveElements(Iterable<ClassElement> recents) { | |
419 if (!hasEnqueuedReflectiveElements) { | |
420 logEnqueueReflectiveAction("!START enqueueAll"); | |
421 // First round of enqueuing, visit everything that is visible to | |
422 // also pick up static top levels, etc. | |
423 // Also, during the first round, consider all classes that have been seen | |
424 // as recently seen, as a couple of rounds of resolution might have run | |
floitsch
2014/06/27 08:59:15
maybe?
... as treeshaking might only be disabled
herhut
2014/06/27 12:34:35
Rephrased:
Also, during the first round, consider
| |
425 // before treeshaking is disabled and we thus enqueue everything. | |
426 recents = seenClasses.toSet(); | |
427 compiler.log('Enqueuing everything'); | |
428 for (LibraryElement lib in compiler.libraries.values) { | |
429 enqueueReflectiveElementsInLibrary(lib, recents, false); | |
430 } | |
431 enqueueReflectiveSpecialClasses(); | |
432 hasEnqueuedReflectiveElements = true; | |
433 hasEnqueuedReflectiveStaticFields = true; | |
434 logEnqueueReflectiveAction("!DONE enqueueAll"); | |
435 } else if (recents.isNotEmpty) { | |
436 // Keep looking at new classes until fixpoint is reached. | |
437 logEnqueueReflectiveAction("!START enqueueRecents"); | |
438 recents.forEach((ClassElement cls) { | |
439 enqueueReflectiveElementsInClass(cls, recents, | |
440 includeElementDueToMirrors(false, cls.library)); | |
441 }); | |
442 logEnqueueReflectiveAction("!DONE enqueueRecents"); | |
350 } | 443 } |
351 hasEnqueuedEverything = true; | |
352 hasEnqueuedReflectiveStaticFields = true; | |
353 } | 444 } |
354 | 445 |
355 /// Enqueue the static fields that have been marked as used by reflective | 446 /// Enqueue the static fields that have been marked as used by reflective |
356 /// usage through `MirrorsUsed`. | 447 /// usage through `MirrorsUsed`. |
357 void enqueueReflectiveStaticFields(Iterable<Element> elements) { | 448 void enqueueReflectiveStaticFields(Iterable<Element> elements) { |
358 if (hasEnqueuedReflectiveStaticFields) return; | 449 if (hasEnqueuedReflectiveStaticFields) return; |
359 hasEnqueuedReflectiveStaticFields = true; | 450 hasEnqueuedReflectiveStaticFields = true; |
360 for (Element element in elements) { | 451 for (Element element in elements) { |
361 pretendElementWasUsed(element, compiler.mirrorDependencies); | 452 enqueueReflectiveMember(element, true); |
362 } | 453 } |
363 } | 454 } |
364 | 455 |
365 processLink(Map<String, Link<Element>> map, | 456 processLink(Map<String, Link<Element>> map, |
366 String memberName, | 457 String memberName, |
367 bool f(Element e)) { | 458 bool f(Element e)) { |
368 Link<Element> members = map[memberName]; | 459 Link<Element> members = map[memberName]; |
369 if (members != null) { | 460 if (members != null) { |
370 // [f] might add elements to [: map[memberName] :] during the loop below | 461 // [f] might add elements to [: map[memberName] :] during the loop below |
371 // so we create a new list for [: map[memberName] :] and prepend the | 462 // so we create a new list for [: map[memberName] :] and prepend the |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
521 } | 612 } |
522 | 613 |
523 | 614 |
524 void registerIfGeneric(Element element, Registry registry) { | 615 void registerIfGeneric(Element element, Registry registry) { |
525 if (element.computeType(compiler).containsTypeVariables) { | 616 if (element.computeType(compiler).containsTypeVariables) { |
526 compiler.backend.registerGenericClosure(element, this, registry); | 617 compiler.backend.registerGenericClosure(element, this, registry); |
527 universe.genericClosures.add(element); | 618 universe.genericClosures.add(element); |
528 } | 619 } |
529 } | 620 } |
530 | 621 |
531 void registerClosure(Element element, Registry registry) { | 622 void registerClosure(Element element, Registry registry) { |
Johnni Winther
2014/06/27 07:43:00
Change [Element] to [FunctionElement].
herhut
2014/06/27 12:34:36
Done.
| |
623 universe.allClosures.add(element); | |
532 registerIfGeneric(element, registry); | 624 registerIfGeneric(element, registry); |
533 } | 625 } |
534 | 626 |
535 void forEach(f(WorkItem work)) { | 627 void forEach(f(WorkItem work)) { |
536 do { | 628 do { |
537 while (!queue.isEmpty) { | 629 while (queue.isNotEmpty) { |
538 // TODO(johnniwinther): Find an optimal process order. | 630 // TODO(johnniwinther): Find an optimal process order. |
539 f(queue.removeLast()); | 631 f(queue.removeLast()); |
540 } | 632 } |
541 onQueueEmpty(); | 633 List recents = recentClasses.toList(growable: false); |
542 } while (!queue.isEmpty); | 634 recentClasses.clear(); |
635 if (!onQueueEmpty(recents)) recentClasses.addAll(recents); | |
636 } while (queue.isNotEmpty || recentClasses.isNotEmpty); | |
543 } | 637 } |
544 | 638 |
545 void onQueueEmpty() { | 639 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] |
546 compiler.backend.onQueueEmpty(this); | 640 /// contains the set of all classes seen for the first time since |
641 /// [onQueueEmpty] was called last. A return value of [true] indicates that | |
642 /// the [recentClasses] have been processed and may be cleared. If [false] is | |
643 /// returned, [onQueueEmpty] will be called once the queue is empty again (or | |
644 /// still empty) and [recentClasses] will be a superset of the current value. | |
645 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { | |
646 return compiler.backend.onQueueEmpty(this, recentClasses); | |
547 } | 647 } |
548 | 648 |
549 void logSummary(log(message)) { | 649 void logSummary(log(message)) { |
550 _logSpecificSummary(log); | 650 _logSpecificSummary(log); |
551 nativeEnqueuer.logSummary(log); | 651 nativeEnqueuer.logSummary(log); |
552 } | 652 } |
553 | 653 |
554 /// Log summary specific to the concrete enqueuer. | 654 /// Log summary specific to the concrete enqueuer. |
555 void _logSpecificSummary(log(message)); | 655 void _logSpecificSummary(log(message)); |
556 | 656 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
596 resolvedElements.add(element); | 696 resolvedElements.add(element); |
597 } | 697 } |
598 | 698 |
599 /// Returns [:true:] if [element] has actually been used. | 699 /// Returns [:true:] if [element] has actually been used. |
600 bool isLive(Element element) { | 700 bool isLive(Element element) { |
601 if (seenClasses.contains(element)) return true; | 701 if (seenClasses.contains(element)) return true; |
602 if (hasBeenResolved(element)) return true; | 702 if (hasBeenResolved(element)) return true; |
603 return false; | 703 return false; |
604 } | 704 } |
605 | 705 |
706 /** | |
707 * Decides whether an element should be included to satisfy requirements | |
708 * of the mirror system. | |
709 * | |
710 * During resoltion, we have to resort to matching elements against the | |
Johnni Winther
2014/06/27 07:43:01
'resoltion' -> 'resolution'.
karlklose
2014/06/27 07:45:57
'resoltion' -> 'resolution'.
herhut
2014/06/27 12:34:36
Done.
herhut
2014/06/27 12:34:37
Done.
| |
711 * [MirrorsUsed] pattern, as we do not have a complete picture of the world, | |
712 * yet. | |
713 */ | |
714 bool includeElementDueToMirrors(bool includeEnclosing, Element element) { | |
karlklose
2014/06/27 07:45:57
Does it make sense to move functionality like this
herhut
2014/06/27 12:34:36
Yes, this is also on the list of further refactori
| |
715 return includeEnclosing || compiler.backend.requiredByMirrorSystem(element); | |
716 } | |
717 | |
606 void internalAddToWorkList(Element element) { | 718 void internalAddToWorkList(Element element) { |
607 assert(invariant(element, element is AnalyzableElement, | 719 assert(invariant(element, element is AnalyzableElement, |
608 message: 'Element $element is not analyzable.')); | 720 message: 'Element $element is not analyzable.')); |
609 if (hasBeenResolved(element)) return; | 721 if (hasBeenResolved(element)) return; |
610 if (queueIsClosed) { | 722 if (queueIsClosed) { |
611 throw new SpannableAssertionFailure(element, | 723 throw new SpannableAssertionFailure(element, |
612 "Resolution work list is closed. Trying to add $element."); | 724 "Resolution work list is closed. Trying to add $element."); |
613 } | 725 } |
614 | 726 |
615 compiler.world.registerUsedElement(element); | 727 compiler.world.registerUsedElement(element); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
682 */ | 794 */ |
683 void addDeferredAction(Element element, DeferredAction action) { | 795 void addDeferredAction(Element element, DeferredAction action) { |
684 if (queueIsClosed) { | 796 if (queueIsClosed) { |
685 throw new SpannableAssertionFailure(element, | 797 throw new SpannableAssertionFailure(element, |
686 "Resolution work list is closed. " | 798 "Resolution work list is closed. " |
687 "Trying to add deferred action for $element"); | 799 "Trying to add deferred action for $element"); |
688 } | 800 } |
689 deferredTaskQueue.add(new DeferredTask(element, action)); | 801 deferredTaskQueue.add(new DeferredTask(element, action)); |
690 } | 802 } |
691 | 803 |
692 void onQueueEmpty() { | 804 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { |
693 emptyDeferredTaskQueue(); | 805 emptyDeferredTaskQueue(); |
694 super.onQueueEmpty(); | 806 return super.onQueueEmpty(recentClasses); |
695 } | 807 } |
696 | 808 |
697 void emptyDeferredTaskQueue() { | 809 void emptyDeferredTaskQueue() { |
698 while (!deferredTaskQueue.isEmpty) { | 810 while (!deferredTaskQueue.isEmpty) { |
699 DeferredTask task = deferredTaskQueue.removeFirst(); | 811 DeferredTask task = deferredTaskQueue.removeFirst(); |
700 compiler.withCurrentElement(task.element, task.action); | 812 compiler.withCurrentElement(task.element, task.action); |
701 } | 813 } |
702 } | 814 } |
703 | 815 |
704 void registerJsCall(Send node, ResolverVisitor resolver) { | 816 void registerJsCall(Send node, ResolverVisitor resolver) { |
(...skipping 15 matching lines...) Expand all Loading... | |
720 | 832 |
721 CodegenEnqueuer(Compiler compiler, | 833 CodegenEnqueuer(Compiler compiler, |
722 ItemCompilationContext itemCompilationContextCreator()) | 834 ItemCompilationContext itemCompilationContextCreator()) |
723 : queue = new Queue<CodegenWorkItem>(), | 835 : queue = new Queue<CodegenWorkItem>(), |
724 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), | 836 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), |
725 super('codegen enqueuer', compiler, itemCompilationContextCreator); | 837 super('codegen enqueuer', compiler, itemCompilationContextCreator); |
726 | 838 |
727 bool isProcessed(Element member) => | 839 bool isProcessed(Element member) => |
728 member.isAbstract || generatedCode.containsKey(member); | 840 member.isAbstract || generatedCode.containsKey(member); |
729 | 841 |
842 /** | |
843 * Decides whether an element should be included to satisfy requirements | |
844 * of the mirror system. | |
845 * | |
846 * For code generation, we rely on the precomputed set of elements that takes | |
847 * subtyping constraints into account. | |
848 */ | |
849 bool includeElementDueToMirrors(bool includeEnclosing, Element element) { | |
850 return compiler.backend.isAccessibleByReflection(element); | |
851 } | |
852 | |
730 void internalAddToWorkList(Element element) { | 853 void internalAddToWorkList(Element element) { |
731 if (compiler.hasIncrementalSupport) { | 854 if (compiler.hasIncrementalSupport) { |
732 newlyEnqueuedElements.add(element); | 855 newlyEnqueuedElements.add(element); |
733 } | 856 } |
734 // Don't generate code for foreign elements. | 857 // Don't generate code for foreign elements. |
735 if (element.isForeign(compiler)) return; | 858 if (element.isForeign(compiler)) return; |
736 | 859 |
737 // Codegen inlines field initializers. It only needs to generate | 860 // Codegen inlines field initializers. It only needs to generate |
738 // code for checked setters. | 861 // code for checked setters. |
739 if (element.isField && element.isInstanceMember) { | 862 if (element.isField && element.isInstanceMember) { |
740 if (!compiler.enableTypeAssertions | 863 if (!compiler.enableTypeAssertions |
741 || element.enclosingElement.isClosure) { | 864 || element.enclosingElement.isClosure) { |
742 return; | 865 return; |
743 } | 866 } |
744 } | 867 } |
745 | 868 |
746 if (queueIsClosed) { | 869 if (queueIsClosed) { |
747 throw new SpannableAssertionFailure(element, | 870 throw new SpannableAssertionFailure(element, |
748 "Codegen work list is closed. Trying to add $element"); | 871 "Codegen work list is closed. Trying to add $element"); |
749 } | 872 } |
750 CodegenWorkItem workItem = new CodegenWorkItem( | 873 CodegenWorkItem workItem = new CodegenWorkItem( |
751 element, itemCompilationContextCreator()); | 874 element, itemCompilationContextCreator()); |
752 queue.add(workItem); | 875 queue.add(workItem); |
753 } | 876 } |
754 | 877 |
755 void _logSpecificSummary(log(message)) { | 878 void _logSpecificSummary(log(message)) { |
756 log('Compiled ${generatedCode.length} methods.'); | 879 log('Compiled ${generatedCode.length} methods.'); |
757 } | 880 } |
758 } | 881 } |
OLD | NEW |