| 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 22 matching lines...) Expand all Loading... |
| 33 } | 33 } |
| 34 | 34 |
| 35 abstract class Enqueuer { | 35 abstract class Enqueuer { |
| 36 final String name; | 36 final String name; |
| 37 final Compiler compiler; // TODO(ahe): Remove this dependency. | 37 final Compiler compiler; // TODO(ahe): Remove this dependency. |
| 38 final ItemCompilationContextCreator itemCompilationContextCreator; | 38 final ItemCompilationContextCreator itemCompilationContextCreator; |
| 39 final Map<String, Set<Element>> instanceMembersByName | 39 final Map<String, Set<Element>> instanceMembersByName |
| 40 = new Map<String, Set<Element>>(); | 40 = new Map<String, Set<Element>>(); |
| 41 final Map<String, Set<Element>> instanceFunctionsByName | 41 final Map<String, Set<Element>> instanceFunctionsByName |
| 42 = new Map<String, Set<Element>>(); | 42 = new Map<String, Set<Element>>(); |
| 43 final Set<ClassElement> _seenClasses = new Set<ClassElement>(); | 43 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); |
| 44 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); | 44 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); |
| 45 final Universe universe = new Universe(); | 45 final Universe universe = new Universe(); |
| 46 | 46 |
| 47 static final TRACE_MIRROR_ENQUEUING = | 47 static final TRACE_MIRROR_ENQUEUING = |
| 48 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); | 48 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); |
| 49 | 49 |
| 50 bool queueIsClosed = false; | 50 bool queueIsClosed = false; |
| 51 EnqueueTask task; | 51 EnqueueTask task; |
| 52 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask | 52 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask |
| 53 | 53 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 84 */ | 84 */ |
| 85 bool internalAddToWorkList(Element element); | 85 bool internalAddToWorkList(Element element); |
| 86 | 86 |
| 87 void registerInstantiatedType(InterfaceType type, Registry registry, | 87 void registerInstantiatedType(InterfaceType type, Registry registry, |
| 88 {bool mirrorUsage: false}) { | 88 {bool mirrorUsage: false}) { |
| 89 task.measure(() { | 89 task.measure(() { |
| 90 ClassElement cls = type.element; | 90 ClassElement cls = type.element; |
| 91 registry.registerDependency(cls); | 91 registry.registerDependency(cls); |
| 92 cls.ensureResolved(compiler); | 92 cls.ensureResolved(compiler); |
| 93 universe.registerTypeInstantiation(type, byMirrors: mirrorUsage); | 93 universe.registerTypeInstantiation(type, byMirrors: mirrorUsage); |
| 94 onRegisterInstantiatedClass(cls); | 94 processInstantiatedClass(cls); |
| 95 }); | 95 }); |
| 96 } | 96 } |
| 97 | 97 |
| 98 void registerInstantiatedClass(ClassElement cls, Registry registry, | 98 void registerInstantiatedClass(ClassElement cls, Registry registry, |
| 99 {bool mirrorUsage: false}) { | 99 {bool mirrorUsage: false}) { |
| 100 cls.ensureResolved(compiler); | 100 cls.ensureResolved(compiler); |
| 101 registerInstantiatedType(cls.rawType, registry, mirrorUsage: mirrorUsage); | 101 registerInstantiatedType(cls.rawType, registry, mirrorUsage: mirrorUsage); |
| 102 } | 102 } |
| 103 | 103 |
| 104 bool checkNoEnqueuedInvokedInstanceMethods() { | 104 bool checkNoEnqueuedInvokedInstanceMethods() { |
| 105 return filter.checkNoEnqueuedInvokedInstanceMethods(this); | 105 return filter.checkNoEnqueuedInvokedInstanceMethods(this); |
| 106 } | 106 } |
| 107 | 107 |
| 108 void processInstantiatedClass(ClassElement cls) { | 108 void processInstantiatedClassMembers(ClassElement cls) { |
| 109 cls.implementation.forEachMember(processInstantiatedClassMember); | 109 cls.implementation.forEachMember(processInstantiatedClassMember); |
| 110 } | 110 } |
| 111 | 111 |
| 112 void processInstantiatedClassMember(ClassElement cls, Element member) { | 112 void processInstantiatedClassMember(ClassElement cls, Element member) { |
| 113 assert(invariant(member, member.isDeclaration)); | 113 assert(invariant(member, member.isDeclaration)); |
| 114 if (isProcessed(member)) return; | 114 if (isProcessed(member)) return; |
| 115 if (!member.isInstanceMember) return; | 115 if (!member.isInstanceMember) return; |
| 116 | 116 |
| 117 String memberName = member.name; | 117 String memberName = member.name; |
| 118 | 118 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 | 207 |
| 208 // The element is not yet used. Add it to the list of instance | 208 // The element is not yet used. Add it to the list of instance |
| 209 // members to still be processed. | 209 // members to still be processed. |
| 210 instanceMembersByName.putIfAbsent(memberName, () => new Set<Element>()) | 210 instanceMembersByName.putIfAbsent(memberName, () => new Set<Element>()) |
| 211 .add(member); | 211 .add(member); |
| 212 } | 212 } |
| 213 | 213 |
| 214 void enableNoSuchMethod(Element element) {} | 214 void enableNoSuchMethod(Element element) {} |
| 215 void enableIsolateSupport() {} | 215 void enableIsolateSupport() {} |
| 216 | 216 |
| 217 void onRegisterInstantiatedClass(ClassElement cls) { | 217 void processInstantiatedClass(ClassElement cls) { |
| 218 task.measure(() { | 218 task.measure(() { |
| 219 if (_seenClasses.contains(cls)) return; | 219 if (_processedClasses.contains(cls)) return; |
| 220 // The class must be resolved to compute the set of all | 220 // The class must be resolved to compute the set of all |
| 221 // supertypes. | 221 // supertypes. |
| 222 cls.ensureResolved(compiler); | 222 cls.ensureResolved(compiler); |
| 223 | 223 |
| 224 void processClass(ClassElement cls) { | 224 void processClass(ClassElement cls) { |
| 225 if (_seenClasses.contains(cls)) return; | 225 if (_processedClasses.contains(cls)) return; |
| 226 | 226 |
| 227 _seenClasses.add(cls); | 227 _processedClasses.add(cls); |
| 228 recentClasses.add(cls); | 228 recentClasses.add(cls); |
| 229 cls.ensureResolved(compiler); | 229 cls.ensureResolved(compiler); |
| 230 cls.implementation.forEachMember(processInstantiatedClassMember); | 230 cls.implementation.forEachMember(processInstantiatedClassMember); |
| 231 if (isResolutionQueue) { | 231 if (isResolutionQueue) { |
| 232 compiler.resolver.checkClass(cls); | 232 compiler.resolver.checkClass(cls); |
| 233 } | 233 } |
| 234 // We only tell the backend once that [cls] was instantiated, so | 234 // We only tell the backend once that [cls] was instantiated, so |
| 235 // any additional dependencies must be treated as global | 235 // any additional dependencies must be treated as global |
| 236 // dependencies. | 236 // dependencies. |
| 237 compiler.backend.registerInstantiatedClass( | 237 compiler.backend.registerInstantiatedClass( |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 /// annotation or, in lack thereof, all elements. | 403 /// annotation or, in lack thereof, all elements. |
| 404 void enqueueReflectiveElements(Iterable<ClassElement> recents) { | 404 void enqueueReflectiveElements(Iterable<ClassElement> recents) { |
| 405 if (!hasEnqueuedReflectiveElements) { | 405 if (!hasEnqueuedReflectiveElements) { |
| 406 logEnqueueReflectiveAction("!START enqueueAll"); | 406 logEnqueueReflectiveAction("!START enqueueAll"); |
| 407 // First round of enqueuing, visit everything that is visible to | 407 // First round of enqueuing, visit everything that is visible to |
| 408 // also pick up static top levels, etc. | 408 // also pick up static top levels, etc. |
| 409 // Also, during the first round, consider all classes that have been seen | 409 // 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 | 410 // 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 | 411 // have run before tree shaking is disabled and thus everything is |
| 412 // enqueued. | 412 // enqueued. |
| 413 recents = _seenClasses.toSet(); | 413 recents = _processedClasses.toSet(); |
| 414 compiler.log('Enqueuing everything'); | 414 compiler.log('Enqueuing everything'); |
| 415 for (LibraryElement lib in compiler.libraryLoader.libraries) { | 415 for (LibraryElement lib in compiler.libraryLoader.libraries) { |
| 416 enqueueReflectiveElementsInLibrary(lib, recents); | 416 enqueueReflectiveElementsInLibrary(lib, recents); |
| 417 } | 417 } |
| 418 enqueueReflectiveSpecialClasses(); | 418 enqueueReflectiveSpecialClasses(); |
| 419 hasEnqueuedReflectiveElements = true; | 419 hasEnqueuedReflectiveElements = true; |
| 420 hasEnqueuedReflectiveStaticFields = true; | 420 hasEnqueuedReflectiveStaticFields = true; |
| 421 logEnqueueReflectiveAction("!DONE enqueueAll"); | 421 logEnqueueReflectiveAction("!DONE enqueueAll"); |
| 422 } else if (recents.isNotEmpty) { | 422 } else if (recents.isNotEmpty) { |
| 423 // Keep looking at new classes until fixpoint is reached. | 423 // Keep looking at new classes until fixpoint is reached. |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 nativeEnqueuer.logSummary(log); | 632 nativeEnqueuer.logSummary(log); |
| 633 } | 633 } |
| 634 | 634 |
| 635 /// Log summary specific to the concrete enqueuer. | 635 /// Log summary specific to the concrete enqueuer. |
| 636 void _logSpecificSummary(log(message)); | 636 void _logSpecificSummary(log(message)); |
| 637 | 637 |
| 638 String toString() => 'Enqueuer($name)'; | 638 String toString() => 'Enqueuer($name)'; |
| 639 | 639 |
| 640 void forgetElement(Element element) { | 640 void forgetElement(Element element) { |
| 641 universe.forgetElement(element, compiler); | 641 universe.forgetElement(element, compiler); |
| 642 _seenClasses.remove(element); | 642 _processedClasses.remove(element); |
| 643 } | 643 } |
| 644 } | 644 } |
| 645 | 645 |
| 646 /// [Enqueuer] which is specific to resolution. | 646 /// [Enqueuer] which is specific to resolution. |
| 647 class ResolutionEnqueuer extends Enqueuer { | 647 class ResolutionEnqueuer extends Enqueuer { |
| 648 /** | 648 /** |
| 649 * Map from declaration elements to the [TreeElements] object holding the | 649 * Map from declaration elements to the [TreeElements] object holding the |
| 650 * resolution mapping for the element implementation. | 650 * resolution mapping for the element implementation. |
| 651 * | 651 * |
| 652 * Invariant: Key elements are declaration elements. | 652 * Invariant: Key elements are declaration elements. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 675 /// Returns `true` if [element] has been processed by the resolution enqueuer. | 675 /// Returns `true` if [element] has been processed by the resolution enqueuer. |
| 676 bool hasBeenResolved(Element element) { | 676 bool hasBeenResolved(Element element) { |
| 677 return resolvedElements.contains(element.analyzableElement.declaration); | 677 return resolvedElements.contains(element.analyzableElement.declaration); |
| 678 } | 678 } |
| 679 | 679 |
| 680 /// Registers [element] as resolved for the resolution enqueuer. | 680 /// Registers [element] as resolved for the resolution enqueuer. |
| 681 void registerResolvedElement(AstElement element) { | 681 void registerResolvedElement(AstElement element) { |
| 682 resolvedElements.add(element); | 682 resolvedElements.add(element); |
| 683 } | 683 } |
| 684 | 684 |
| 685 /// Returns [:true:] if [element] has actually been used. | |
| 686 bool isLive(Element element) { | |
| 687 if (_seenClasses.contains(element)) return true; | |
| 688 if (hasBeenResolved(element)) return true; | |
| 689 return false; | |
| 690 } | |
| 691 | |
| 692 /** | 685 /** |
| 693 * Decides whether an element should be included to satisfy requirements | 686 * Decides whether an element should be included to satisfy requirements |
| 694 * of the mirror system. | 687 * of the mirror system. |
| 695 * | 688 * |
| 696 * During resolution, we have to resort to matching elements against the | 689 * During resolution, we have to resort to matching elements against the |
| 697 * [MirrorsUsed] pattern, as we do not have a complete picture of the world, | 690 * [MirrorsUsed] pattern, as we do not have a complete picture of the world, |
| 698 * yet. | 691 * yet. |
| 699 */ | 692 */ |
| 700 bool shouldIncludeElementDueToMirrors(Element element, | 693 bool shouldIncludeElementDueToMirrors(Element element, |
| 701 {bool includedEnclosing}) { | 694 {bool includedEnclosing}) { |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 } | 874 } |
| 882 } | 875 } |
| 883 } | 876 } |
| 884 } | 877 } |
| 885 | 878 |
| 886 /// Parameterizes filtering of which work items are enqueued. | 879 /// Parameterizes filtering of which work items are enqueued. |
| 887 class QueueFilter { | 880 class QueueFilter { |
| 888 bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) { | 881 bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) { |
| 889 enqueuer.task.measure(() { | 882 enqueuer.task.measure(() { |
| 890 // Run through the classes and see if we need to compile methods. | 883 // Run through the classes and see if we need to compile methods. |
| 891 for (ClassElement classElement in enqueuer.universe.instantiatedClasses) { | 884 for (ClassElement classElement in |
| 885 enqueuer.universe.directlyInstantiatedClasses) { |
| 892 for (ClassElement currentClass = classElement; | 886 for (ClassElement currentClass = classElement; |
| 893 currentClass != null; | 887 currentClass != null; |
| 894 currentClass = currentClass.superclass) { | 888 currentClass = currentClass.superclass) { |
| 895 enqueuer.processInstantiatedClass(currentClass); | 889 enqueuer.processInstantiatedClassMembers(currentClass); |
| 896 } | 890 } |
| 897 } | 891 } |
| 898 }); | 892 }); |
| 899 return true; | 893 return true; |
| 900 } | 894 } |
| 901 | 895 |
| 902 void processWorkItem(void f(WorkItem work), WorkItem work) { | 896 void processWorkItem(void f(WorkItem work), WorkItem work) { |
| 903 f(work); | 897 f(work); |
| 904 } | 898 } |
| 905 } | 899 } |
| 906 | 900 |
| 907 void removeFromSet(Map<String, Set<Element>> map, Element element) { | 901 void removeFromSet(Map<String, Set<Element>> map, Element element) { |
| 908 Set<Element> set = map[element.name]; | 902 Set<Element> set = map[element.name]; |
| 909 if (set == null) return; | 903 if (set == null) return; |
| 910 set.remove(element); | 904 set.remove(element); |
| 911 } | 905 } |
| OLD | NEW |