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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/enqueue.dart

Issue 340783011: Take inheritance into account when computing the elements accessible by mirrors. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: rebased + fixes Created 6 years, 5 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 | Annotate | Revision Log
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 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;
11 final CodegenEnqueuer codegen; 11 final CodegenEnqueuer codegen;
12 12
13 /// A reverse map from name to *all* elements with that name, not
14 /// just instance members of instantiated classes.
15 final Map<String, Link<Element>> allElementsByName
16 = new Map<String, Link<Element>>();
17
18 void ensureAllElementsByName() {
19 if (!allElementsByName.isEmpty) return;
20
21 void addMemberByName(Element element) {
22 element = element.declaration;
23 String name = element.name;
24 ScopeContainerElement container = null;
25 if (element.isLibrary) {
26 LibraryElement library = element;
27 container = library;
28 // TODO(ahe): Is this right? Is this necessary?
29 name = library.getLibraryOrScriptName();
30 } else if (element.isClass) {
31 ClassElement cls = element;
32 cls.ensureResolved(compiler);
33 container = cls;
34 for (var link = cls.computeTypeParameters(compiler);
35 !link.isEmpty;
36 link = link.tail) {
37 addMemberByName(link.head.element);
38 }
39 }
40 allElementsByName[name] = allElementsByName.putIfAbsent(
41 name, () => const Link<Element>()).prepend(element);
42 if (container != null) {
43 container.forEachLocalMember(addMemberByName);
44 }
45 }
46
47 compiler.libraryLoader.libraries.forEach(addMemberByName);
48 }
49
50 String get name => 'Enqueue'; 13 String get name => 'Enqueue';
51 14
52 EnqueueTask(Compiler compiler) 15 EnqueueTask(Compiler compiler)
53 : resolution = new ResolutionEnqueuer( 16 : resolution = new ResolutionEnqueuer(
54 compiler, compiler.backend.createItemCompilationContext), 17 compiler, compiler.backend.createItemCompilationContext),
55 codegen = new CodegenEnqueuer( 18 codegen = new CodegenEnqueuer(
56 compiler, compiler.backend.createItemCompilationContext), 19 compiler, compiler.backend.createItemCompilationContext),
57 super(compiler) { 20 super(compiler) {
58 codegen.task = this; 21 codegen.task = this;
59 resolution.task = this; 22 resolution.task = this;
60 23
61 codegen.nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(codegen); 24 codegen.nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(codegen);
62 resolution.nativeEnqueuer = 25 resolution.nativeEnqueuer =
63 compiler.backend.nativeResolutionEnqueuer(resolution); 26 compiler.backend.nativeResolutionEnqueuer(resolution);
64 } 27 }
65 } 28 }
66 29
67 abstract class Enqueuer { 30 abstract class Enqueuer {
68 final String name; 31 final String name;
69 final Compiler compiler; // TODO(ahe): Remove this dependency. 32 final Compiler compiler; // TODO(ahe): Remove this dependency.
70 final ItemCompilationContextCreator itemCompilationContextCreator; 33 final ItemCompilationContextCreator itemCompilationContextCreator;
71 final Map<String, Link<Element>> instanceMembersByName 34 final Map<String, Link<Element>> instanceMembersByName
72 = new Map<String, Link<Element>>(); 35 = new Map<String, Link<Element>>();
73 final Map<String, Link<Element>> instanceFunctionsByName 36 final Map<String, Link<Element>> instanceFunctionsByName
74 = new Map<String, Link<Element>>(); 37 = new Map<String, Link<Element>>();
75 final Set<ClassElement> seenClasses = new Set<ClassElement>(); 38 final Set<ClassElement> seenClasses = new Set<ClassElement>();
39 Set<ClassElement> recentClasses = new Setlet<ClassElement>();
76 final Universe universe = new Universe(); 40 final Universe universe = new Universe();
77 41
42 static final TRACE_MIRROR_ENQUEUING =
43 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING");
44
78 bool queueIsClosed = false; 45 bool queueIsClosed = false;
79 EnqueueTask task; 46 EnqueueTask task;
80 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask 47 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask
81 48
82 bool hasEnqueuedEverything = false; 49 bool hasEnqueuedReflectiveElements = false;
83 bool hasEnqueuedReflectiveStaticFields = false; 50 bool hasEnqueuedReflectiveStaticFields = false;
84 51
85 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator); 52 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator);
86 53
87 Queue<WorkItem> get queue; 54 Queue<WorkItem> get queue;
88 bool get queueIsEmpty => queue.isEmpty; 55 bool get queueIsEmpty => queue.isEmpty;
89 56
90 /// Returns [:true:] if this enqueuer is the resolution enqueuer. 57 /// Returns [:true:] if this enqueuer is the resolution enqueuer.
91 bool get isResolutionQueue => false; 58 bool get isResolutionQueue => false;
92 59
93 /// Returns [:true:] if [member] has been processed by this enqueuer. 60 /// Returns [:true:] if [member] has been processed by this enqueuer.
94 bool isProcessed(Element member); 61 bool isProcessed(Element member);
95 62
96 /** 63 /**
97 * Documentation wanted -- johnniwinther 64 * Documentation wanted -- johnniwinther
98 * 65 *
99 * Invariant: [element] must be a declaration element. 66 * Invariant: [element] must be a declaration element.
100 */ 67 */
101 void addToWorkList(Element element) { 68 void addToWorkList(Element element) {
102 assert(invariant(element, element.isDeclaration)); 69 assert(invariant(element, element.isDeclaration));
103 internalAddToWorkList(element); 70 internalAddToWorkList(element);
104 } 71 }
105 72
106 /** 73 /**
107 * Adds [element] to the work list if it has not already been processed. 74 * Adds [element] to the work list if it has not already been processed.
108 */ 75 */
109 void internalAddToWorkList(Element element); 76 void internalAddToWorkList(Element element);
110 77
111 void registerInstantiatedType(InterfaceType type, Registry registry) { 78 void registerInstantiatedType(InterfaceType type, Registry registry,
79 {mirrorUsage: false}) {
112 task.measure(() { 80 task.measure(() {
113 ClassElement cls = type.element; 81 ClassElement cls = type.element;
114 registry.registerDependency(cls); 82 registry.registerDependency(cls);
115 cls.ensureResolved(compiler); 83 cls.ensureResolved(compiler);
116 universe.instantiatedTypes.add(type); 84 universe.instantiatedTypes.add(type);
117 if (!cls.isAbstract 85 if (!cls.isAbstract
118 // We can't use the closed-world assumption with native abstract 86 // We can't use the closed-world assumption with native abstract
119 // classes; a native abstract class may have non-abstract subclasses 87 // classes; a native abstract class may have non-abstract subclasses
120 // not declared to the program. Instances of these classes are 88 // not declared to the program. Instances of these classes are
121 // indistinguishable from the abstract class. 89 // indistinguishable from the abstract class.
122 || cls.isNative) { 90 || cls.isNative
91 // Likewise, if this registration comes from the mirror system,
92 // all bets are off.
93 // TODO(herhut): Track classes required by mirrors seperately.
94 || mirrorUsage) {
123 universe.instantiatedClasses.add(cls); 95 universe.instantiatedClasses.add(cls);
124 } 96 }
125 onRegisterInstantiatedClass(cls); 97 onRegisterInstantiatedClass(cls);
126 }); 98 });
127 } 99 }
128 100
129 void registerInstantiatedClass(ClassElement cls, Registry registry) { 101 void registerInstantiatedClass(ClassElement cls, Registry registry,
102 {mirrorUsage: false}) {
130 cls.ensureResolved(compiler); 103 cls.ensureResolved(compiler);
131 registerInstantiatedType(cls.rawType, registry); 104 registerInstantiatedType(cls.rawType, registry, mirrorUsage: mirrorUsage);
132 } 105 }
133 106
134 bool checkNoEnqueuedInvokedInstanceMethods() { 107 bool checkNoEnqueuedInvokedInstanceMethods() {
135 task.measure(() { 108 task.measure(() {
136 // Run through the classes and see if we need to compile methods. 109 // Run through the classes and see if we need to compile methods.
137 for (ClassElement classElement in universe.instantiatedClasses) { 110 for (ClassElement classElement in universe.instantiatedClasses) {
138 for (ClassElement currentClass = classElement; 111 for (ClassElement currentClass = classElement;
139 currentClass != null; 112 currentClass != null;
140 currentClass = currentClass.superclass) { 113 currentClass = currentClass.superclass) {
141 processInstantiatedClass(currentClass); 114 processInstantiatedClass(currentClass);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 task.measure(() { 226 task.measure(() {
254 if (seenClasses.contains(cls)) return; 227 if (seenClasses.contains(cls)) return;
255 // The class must be resolved to compute the set of all 228 // The class must be resolved to compute the set of all
256 // supertypes. 229 // supertypes.
257 cls.ensureResolved(compiler); 230 cls.ensureResolved(compiler);
258 231
259 void processClass(ClassElement cls) { 232 void processClass(ClassElement cls) {
260 if (seenClasses.contains(cls)) return; 233 if (seenClasses.contains(cls)) return;
261 234
262 seenClasses.add(cls); 235 seenClasses.add(cls);
236 recentClasses.add(cls);
263 cls.ensureResolved(compiler); 237 cls.ensureResolved(compiler);
264 cls.implementation.forEachMember(processInstantiatedClassMember); 238 cls.implementation.forEachMember(processInstantiatedClassMember);
265 if (isResolutionQueue) { 239 if (isResolutionQueue) {
266 compiler.resolver.checkClass(cls); 240 compiler.resolver.checkClass(cls);
267 } 241 }
268 // We only tell the backend once that [cls] was instantiated, so 242 // We only tell the backend once that [cls] was instantiated, so
269 // any additional dependencies must be treated as global 243 // any additional dependencies must be treated as global
270 // dependencies. 244 // dependencies.
271 compiler.backend.registerInstantiatedClass( 245 compiler.backend.registerInstantiatedClass(
272 cls, this, compiler.globalDependencies); 246 cls, this, compiler.globalDependencies);
(...skipping 28 matching lines...) Expand all
301 registerNewSelector(selector, universe.invokedGetters); 275 registerNewSelector(selector, universe.invokedGetters);
302 }); 276 });
303 } 277 }
304 278
305 void registerInvokedSetter(Selector selector) { 279 void registerInvokedSetter(Selector selector) {
306 task.measure(() { 280 task.measure(() {
307 registerNewSelector(selector, universe.invokedSetters); 281 registerNewSelector(selector, universe.invokedSetters);
308 }); 282 });
309 } 283 }
310 284
311 void pretendElementWasUsed(Element element, Registry registry) { 285 /**
312 if (!compiler.backend.isNeededForReflection(element)) return; 286 * Decides whether an element should be included to satisfy requirements
313 if (Elements.isUnresolved(element)) { 287 * of the mirror system. [includedEnclosing] provides a hint whether the
314 // Ignore. 288 * enclosing element was included.
315 } else if (element.isSynthesized 289 *
316 && element.library.isPlatformLibrary) { 290 * The actual implementation depends on the current compiler phase.
317 // TODO(ahe): Work-around for http://dartbug.com/11205. 291 */
318 } else if (element.isConstructor) { 292 bool shouldIncludeElementDueToMirrors(Element element,
319 ClassElement cls = element.declaration.enclosingClass; 293 {bool includedEnclosing});
320 registerInstantiatedType(cls.rawType, registry); 294
321 registerStaticUse(element.declaration); 295 void logEnqueueReflectiveAction(action, [msg = ""]) {
322 } else if (element.isClass) { 296 if (TRACE_MIRROR_ENQUEUING) {
323 ClassElement cls = element.declaration; 297 print("MIRROR_ENQUEUE (${isResolutionQueue ? "R" : "C"}): $action $msg");
324 registerInstantiatedClass(cls, registry); 298 }
325 // Make sure that even abstract classes are considered instantiated. 299 }
326 universe.instantiatedClasses.add(cls); 300
327 } else if (element.impliesType) { 301 /// Enqeue the constructor [ctor] if it is required for reflection.
328 // Don't enqueue typedefs, and type variables. 302 ///
329 } else if (Elements.isStaticOrTopLevel(element)) { 303 /// [enclosingWasIncluded] provides a hint whether the enclosing element was
330 registerStaticUse(element.declaration); 304 /// needed for reflection.
331 } else if (element.isInstanceMember) { 305 void enqueueReflectiveConstructor(ConstructorElement ctor,
332 Selector selector = new Selector.fromElement(element, compiler); 306 bool enclosingWasIncluded) {
333 registerSelectorUse(selector); 307 if (shouldIncludeElementDueToMirrors(ctor,
334 if (element.isField) { 308 includedEnclosing: enclosingWasIncluded)) {
335 Selector selector = 309 logEnqueueReflectiveAction(ctor);
336 new Selector.setter(element.name, element.library); 310 ClassElement cls = ctor.declaration.enclosingClass;
337 registerInvokedSetter(selector); 311 registerInstantiatedType(cls.rawType, compiler.mirrorDependencies,
312 mirrorUsage: true);
313 registerStaticUse(ctor.declaration);
314 }
315 }
316
317 /// Enqeue the member [element] if it is required for reflection.
318 ///
319 /// [enclosingWasIncluded] provides a hint whether the enclosing element was
320 /// needed for reflection.
321 void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) {
322 if (shouldIncludeElementDueToMirrors(element,
323 includedEnclosing: enclosingWasIncluded)
324 // Do not enqueue typedefs.
325 && !element.impliesType) {
326 logEnqueueReflectiveAction(element);
327 if (Elements.isStaticOrTopLevel(element)) {
328 registerStaticUse(element.declaration);
329 } else if (element.isInstanceMember) {
330 // We need to enqueue all members matching this one in subclasses, as
331 // well.
332 // TODO(herhut): Use TypedSelector.subtype for enqueueing
333 Selector selector = new Selector.fromElement(element, compiler);
334 registerSelectorUse(selector);
335 if (element.isField) {
336 Selector selector =
337 new Selector.setter(element.name, element.library);
338 registerInvokedSetter(selector);
339 }
338 } 340 }
339 } 341 }
340 } 342 }
341 343
342 void enqueueEverything() { 344 /// Enqeue the member [element] if it is required for reflection.
343 if (hasEnqueuedEverything) return; 345 ///
344 compiler.log('Enqueuing everything'); 346 /// [enclosingWasIncluded] provides a hint whether the enclosing element was
345 task.ensureAllElementsByName(); 347 /// needed for reflection.
346 for (Link link in task.allElementsByName.values) { 348 void enqueueReflectiveElementsInClass(ClassElement cls,
347 for (Element element in link) { 349 Iterable<ClassElement> recents,
348 pretendElementWasUsed(element, compiler.mirrorDependencies); 350 bool enclosingWasIncluded) {
351 if (cls.library.isInternalLibrary || cls.isInjected) return;
352 bool includeClass = shouldIncludeElementDueToMirrors(cls,
353 includedEnclosing: enclosingWasIncluded);
354 if (includeClass) {
355 logEnqueueReflectiveAction(cls, "register");
356 ClassElement decl = cls.declaration;
357 registerInstantiatedClass(decl, compiler.mirrorDependencies,
358 mirrorUsage: true);
359 }
360 // If the class is never instantiated, we know nothing of it can possibly
361 // be reflected upon.
362 // TODO(herhut): Add a warning if a mirrors annotation cannot hit.
363 if (recents.contains(cls.declaration)) {
364 logEnqueueReflectiveAction(cls, "members");
365 cls.constructors.forEach((Element element) {
366 enqueueReflectiveConstructor(element, includeClass);
367 });
368 cls.forEachClassMember((Member member) {
369 enqueueReflectiveMember(member.element, includeClass);
370 });
371 }
372 }
373
374 /// Enqeue special classes that might not be visible by normal means or that
375 /// would not normally be enqueued:
376 ///
377 /// [Closure] is treated specially as it is the superclass of all closures.
378 /// Although it is in an internal library, we mark it as reflectable. Note
379 /// that none of its methods are reflectable, unless reflectable by
380 /// inheritance.
381 void enqueueReflectiveSpecialClasses() {
382 Iterable<ClassElement> classes =
383 compiler.backend.classesRequiredForReflection;
384 for (ClassElement cls in classes) {
385 if (compiler.backend.referencedFromMirrorSystem(cls)) {
386 logEnqueueReflectiveAction(cls);
387 registerInstantiatedClass(cls, compiler.mirrorDependencies,
388 mirrorUsage: true);
349 } 389 }
350 } 390 }
351 hasEnqueuedEverything = true; 391 }
352 hasEnqueuedReflectiveStaticFields = true; 392
393 /// Enqeue all local members of the library [lib] if they are required for
394 /// reflection.
395 void enqueueReflectiveElementsInLibrary(LibraryElement lib,
396 Iterable<ClassElement> recents) {
397 bool includeLibrary = shouldIncludeElementDueToMirrors(lib,
398 includedEnclosing: false);
399 lib.forEachLocalMember((Element member) {
400 if (member.isClass) {
401 enqueueReflectiveElementsInClass(member, recents, includeLibrary);
402 } else {
403 enqueueReflectiveMember(member, includeLibrary);
404 }
405 });
406 }
407
408 /// Enqueue all elements that are matched by the mirrors used
409 /// annotation or, in lack thereof, all elements.
410 void enqueueReflectiveElements(Iterable<ClassElement> recents) {
411 if (!hasEnqueuedReflectiveElements) {
412 logEnqueueReflectiveAction("!START enqueueAll");
413 // First round of enqueuing, visit everything that is visible to
414 // also pick up static top levels, etc.
415 // Also, during the first round, consider all classes that have been seen
416 // as recently seen, as we do not know how many rounds of resolution might
417 // have run before tree shaking is disabled and thus everything is
418 // enqueued.
419 recents = seenClasses.toSet();
420 compiler.log('Enqueuing everything');
421 for (LibraryElement lib in compiler.libraryLoader.libraries) {
422 enqueueReflectiveElementsInLibrary(lib, recents);
423 }
424 enqueueReflectiveSpecialClasses();
425 hasEnqueuedReflectiveElements = true;
426 hasEnqueuedReflectiveStaticFields = true;
427 logEnqueueReflectiveAction("!DONE enqueueAll");
428 } else if (recents.isNotEmpty) {
429 // Keep looking at new classes until fixpoint is reached.
430 logEnqueueReflectiveAction("!START enqueueRecents");
431 recents.forEach((ClassElement cls) {
432 enqueueReflectiveElementsInClass(cls, recents,
433 shouldIncludeElementDueToMirrors(cls.library,
434 includedEnclosing: false));
435 });
436 logEnqueueReflectiveAction("!DONE enqueueRecents");
437 }
353 } 438 }
354 439
355 /// Enqueue the static fields that have been marked as used by reflective 440 /// Enqueue the static fields that have been marked as used by reflective
356 /// usage through `MirrorsUsed`. 441 /// usage through `MirrorsUsed`.
357 void enqueueReflectiveStaticFields(Iterable<Element> elements) { 442 void enqueueReflectiveStaticFields(Iterable<Element> elements) {
358 if (hasEnqueuedReflectiveStaticFields) return; 443 if (hasEnqueuedReflectiveStaticFields) return;
359 hasEnqueuedReflectiveStaticFields = true; 444 hasEnqueuedReflectiveStaticFields = true;
360 for (Element element in elements) { 445 for (Element element in elements) {
361 pretendElementWasUsed(element, compiler.mirrorDependencies); 446 enqueueReflectiveMember(element, true);
362 } 447 }
363 } 448 }
364 449
365 processLink(Map<String, Link<Element>> map, 450 processLink(Map<String, Link<Element>> map,
366 String memberName, 451 String memberName,
367 bool f(Element e)) { 452 bool f(Element e)) {
368 Link<Element> members = map[memberName]; 453 Link<Element> members = map[memberName];
369 if (members != null) { 454 if (members != null) {
370 // [f] might add elements to [: map[memberName] :] during the loop below 455 // [f] might add elements to [: map[memberName] :] during the loop below
371 // so we create a new list for [: map[memberName] :] and prepend the 456 // so we create a new list for [: map[memberName] :] and prepend the
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 universe.closurizedMembers.add(element); 595 universe.closurizedMembers.add(element);
511 } 596 }
512 597
513 void registerIfGeneric(Element element, Registry registry) { 598 void registerIfGeneric(Element element, Registry registry) {
514 if (element.computeType(compiler).containsTypeVariables) { 599 if (element.computeType(compiler).containsTypeVariables) {
515 compiler.backend.registerGenericClosure(element, this, registry); 600 compiler.backend.registerGenericClosure(element, this, registry);
516 universe.genericClosures.add(element); 601 universe.genericClosures.add(element);
517 } 602 }
518 } 603 }
519 604
520 void registerClosure(Element element, Registry registry) { 605 void registerClosure(FunctionElement element, Registry registry) {
606 universe.allClosures.add(element);
521 registerIfGeneric(element, registry); 607 registerIfGeneric(element, registry);
522 } 608 }
523 609
524 void forEach(f(WorkItem work)) { 610 void forEach(f(WorkItem work)) {
525 do { 611 do {
526 while (!queue.isEmpty) { 612 while (queue.isNotEmpty) {
527 // TODO(johnniwinther): Find an optimal process order. 613 // TODO(johnniwinther): Find an optimal process order.
528 f(queue.removeLast()); 614 f(queue.removeLast());
529 } 615 }
530 onQueueEmpty(); 616 List recents = recentClasses.toList(growable: false);
531 } while (!queue.isEmpty); 617 recentClasses.clear();
618 if (!onQueueEmpty(recents)) recentClasses.addAll(recents);
619 } while (queue.isNotEmpty || recentClasses.isNotEmpty);
532 } 620 }
533 621
534 void onQueueEmpty() { 622 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses]
535 compiler.backend.onQueueEmpty(this); 623 /// contains the set of all classes seen for the first time since
624 /// [onQueueEmpty] was called last. A return value of [true] indicates that
625 /// the [recentClasses] have been processed and may be cleared. If [false] is
626 /// returned, [onQueueEmpty] will be called once the queue is empty again (or
627 /// still empty) and [recentClasses] will be a superset of the current value.
628 bool onQueueEmpty(Iterable<ClassElement> recentClasses) {
629 return compiler.backend.onQueueEmpty(this, recentClasses);
536 } 630 }
537 631
538 void logSummary(log(message)) { 632 void logSummary(log(message)) {
539 _logSpecificSummary(log); 633 _logSpecificSummary(log);
540 nativeEnqueuer.logSummary(log); 634 nativeEnqueuer.logSummary(log);
541 } 635 }
542 636
543 /// Log summary specific to the concrete enqueuer. 637 /// Log summary specific to the concrete enqueuer.
544 void _logSpecificSummary(log(message)); 638 void _logSpecificSummary(log(message));
545 639
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 resolvedElements.add(element); 679 resolvedElements.add(element);
586 } 680 }
587 681
588 /// Returns [:true:] if [element] has actually been used. 682 /// Returns [:true:] if [element] has actually been used.
589 bool isLive(Element element) { 683 bool isLive(Element element) {
590 if (seenClasses.contains(element)) return true; 684 if (seenClasses.contains(element)) return true;
591 if (hasBeenResolved(element)) return true; 685 if (hasBeenResolved(element)) return true;
592 return false; 686 return false;
593 } 687 }
594 688
689 /**
690 * Decides whether an element should be included to satisfy requirements
691 * of the mirror system.
692 *
693 * During resolution, we have to resort to matching elements against the
694 * [MirrorsUsed] pattern, as we do not have a complete picture of the world,
695 * yet.
696 */
697 bool shouldIncludeElementDueToMirrors(Element element,
698 {bool includedEnclosing}) {
699 return includedEnclosing || compiler.backend.requiredByMirrorSystem(element) ;
700 }
701
595 void internalAddToWorkList(Element element) { 702 void internalAddToWorkList(Element element) {
596 assert(invariant(element, element is AnalyzableElement, 703 assert(invariant(element, element is AnalyzableElement,
597 message: 'Element $element is not analyzable.')); 704 message: 'Element $element is not analyzable.'));
598 if (hasBeenResolved(element)) return; 705 if (hasBeenResolved(element)) return;
599 if (queueIsClosed) { 706 if (queueIsClosed) {
600 throw new SpannableAssertionFailure(element, 707 throw new SpannableAssertionFailure(element,
601 "Resolution work list is closed. Trying to add $element."); 708 "Resolution work list is closed. Trying to add $element.");
602 } 709 }
603 710
604 compiler.world.registerUsedElement(element); 711 compiler.world.registerUsedElement(element);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 */ 770 */
664 void addDeferredAction(Element element, DeferredAction action) { 771 void addDeferredAction(Element element, DeferredAction action) {
665 if (queueIsClosed) { 772 if (queueIsClosed) {
666 throw new SpannableAssertionFailure(element, 773 throw new SpannableAssertionFailure(element,
667 "Resolution work list is closed. " 774 "Resolution work list is closed. "
668 "Trying to add deferred action for $element"); 775 "Trying to add deferred action for $element");
669 } 776 }
670 deferredTaskQueue.add(new DeferredTask(element, action)); 777 deferredTaskQueue.add(new DeferredTask(element, action));
671 } 778 }
672 779
673 void onQueueEmpty() { 780 bool onQueueEmpty(Iterable<ClassElement> recentClasses) {
674 emptyDeferredTaskQueue(); 781 emptyDeferredTaskQueue();
675 super.onQueueEmpty(); 782 return super.onQueueEmpty(recentClasses);
676 } 783 }
677 784
678 void emptyDeferredTaskQueue() { 785 void emptyDeferredTaskQueue() {
679 while (!deferredTaskQueue.isEmpty) { 786 while (!deferredTaskQueue.isEmpty) {
680 DeferredTask task = deferredTaskQueue.removeFirst(); 787 DeferredTask task = deferredTaskQueue.removeFirst();
681 compiler.withCurrentElement(task.element, task.action); 788 compiler.withCurrentElement(task.element, task.action);
682 } 789 }
683 } 790 }
684 791
685 void registerJsCall(Send node, ResolverVisitor resolver) { 792 void registerJsCall(Send node, ResolverVisitor resolver) {
(...skipping 15 matching lines...) Expand all
701 808
702 CodegenEnqueuer(Compiler compiler, 809 CodegenEnqueuer(Compiler compiler,
703 ItemCompilationContext itemCompilationContextCreator()) 810 ItemCompilationContext itemCompilationContextCreator())
704 : queue = new Queue<CodegenWorkItem>(), 811 : queue = new Queue<CodegenWorkItem>(),
705 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), 812 newlyEnqueuedElements = compiler.cacheStrategy.newSet(),
706 super('codegen enqueuer', compiler, itemCompilationContextCreator); 813 super('codegen enqueuer', compiler, itemCompilationContextCreator);
707 814
708 bool isProcessed(Element member) => 815 bool isProcessed(Element member) =>
709 member.isAbstract || generatedCode.containsKey(member); 816 member.isAbstract || generatedCode.containsKey(member);
710 817
818 /**
819 * Decides whether an element should be included to satisfy requirements
820 * of the mirror system.
821 *
822 * For code generation, we rely on the precomputed set of elements that takes
823 * subtyping constraints into account.
824 */
825 bool shouldIncludeElementDueToMirrors(Element element,
826 {bool includedEnclosing}) {
827 return compiler.backend.isAccessibleByReflection(element);
828 }
829
711 void internalAddToWorkList(Element element) { 830 void internalAddToWorkList(Element element) {
712 if (compiler.hasIncrementalSupport) { 831 if (compiler.hasIncrementalSupport) {
713 newlyEnqueuedElements.add(element); 832 newlyEnqueuedElements.add(element);
714 } 833 }
715 // Don't generate code for foreign elements. 834 // Don't generate code for foreign elements.
716 if (element.isForeign(compiler)) return; 835 if (element.isForeign(compiler)) return;
717 836
718 // Codegen inlines field initializers. It only needs to generate 837 // Codegen inlines field initializers. It only needs to generate
719 // code for checked setters. 838 // code for checked setters.
720 if (element.isField && element.isInstanceMember) { 839 if (element.isField && element.isInstanceMember) {
721 if (!compiler.enableTypeAssertions 840 if (!compiler.enableTypeAssertions
722 || element.enclosingElement.isClosure) { 841 || element.enclosingElement.isClosure) {
723 return; 842 return;
724 } 843 }
725 } 844 }
726 845
727 if (queueIsClosed) { 846 if (queueIsClosed) {
728 throw new SpannableAssertionFailure(element, 847 throw new SpannableAssertionFailure(element,
729 "Codegen work list is closed. Trying to add $element"); 848 "Codegen work list is closed. Trying to add $element");
730 } 849 }
731 CodegenWorkItem workItem = new CodegenWorkItem( 850 CodegenWorkItem workItem = new CodegenWorkItem(
732 element, itemCompilationContextCreator()); 851 element, itemCompilationContextCreator());
733 queue.add(workItem); 852 queue.add(workItem);
734 } 853 }
735 854
736 void _logSpecificSummary(log(message)) { 855 void _logSpecificSummary(log(message)) {
737 log('Compiled ${generatedCode.length} methods.'); 856 log('Compiled ${generatedCode.length} methods.');
738 } 857 }
739 } 858 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698