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

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

Issue 2500373003: Compute WorldImpact for mirror analysis. (Closed)
Patch Set: Remove Enqueuer.registerTypeUse Created 4 years, 1 month 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/js_backend/backend.dart ('k') | pkg/compiler/lib/src/types/types.dart » ('j') | 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) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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.mirrors_handler; 5 library dart2js.mirrors_handler;
6 6
7 import '../common/resolution.dart'; 7 import '../common/resolution.dart';
8 import '../diagnostics/diagnostic_listener.dart'; 8 import '../diagnostics/diagnostic_listener.dart';
9 import '../elements/elements.dart'; 9 import '../elements/elements.dart';
10 import '../enqueue.dart';
11 import '../universe/selector.dart'; 10 import '../universe/selector.dart';
12 import '../universe/use.dart'; 11 import '../universe/use.dart';
12 import '../universe/world_impact.dart';
13 import 'backend.dart'; 13 import 'backend.dart';
14 14
15 class MirrorsAnalysis { 15 class MirrorsAnalysis {
16 final MirrorsHandler resolutionHandler; 16 final MirrorsHandler resolutionHandler;
17 final MirrorsHandler codegenHandler; 17 final MirrorsHandler codegenHandler;
18 18
19 MirrorsAnalysis(JavaScriptBackend backend, Resolution resolution) 19 MirrorsAnalysis(JavaScriptBackend backend, Resolution resolution)
20 : resolutionHandler = new MirrorsHandler(backend, resolution), 20 : resolutionHandler = new MirrorsHandler(backend, resolution),
21 codegenHandler = new MirrorsHandler(backend, resolution); 21 codegenHandler = new MirrorsHandler(backend, resolution);
22 22
23 /// Enqueue all elements that are matched by the mirrors used 23 /// Compute the impact for elements that are matched by the mirrors used
24 /// annotation or, in lack thereof, all elements. 24 /// annotation or, in lack thereof, all elements.
25 // TODO(johnniwinther): Compute [WorldImpact] instead of enqueuing directly. 25 WorldImpact computeImpactForReflectiveElements(
26 void enqueueReflectiveElements(
27 Enqueuer enqueuer,
28 Iterable<ClassElement> recents, 26 Iterable<ClassElement> recents,
29 Iterable<LibraryElement> loadedLibraries) { 27 Iterable<ClassElement> processedClasses,
30 MirrorsHandler handler = 28 Iterable<LibraryElement> loadedLibraries,
31 enqueuer.isResolutionQueue ? resolutionHandler : codegenHandler; 29 {bool forResolution}) {
32 handler.enqueueReflectiveElements(enqueuer, recents, loadedLibraries); 30 MirrorsHandler handler = forResolution ? resolutionHandler : codegenHandler;
31 handler.enqueueReflectiveElements(
32 recents, processedClasses, loadedLibraries);
33 return handler.flush();
33 } 34 }
34 35
35 /// Enqueue the static fields that have been marked as used by reflective 36 /// Compute the impact for the static fields that have been marked as used by
36 /// usage through `MirrorsUsed`. 37 /// reflective usage through `MirrorsUsed`.
37 // TODO(johnniwinther): Compute [WorldImpact] instead of enqueuing directly. 38 WorldImpact computeImpactForReflectiveStaticFields(Iterable<Element> elements,
38 void enqueueReflectiveStaticFields( 39 {bool forResolution}) {
39 Enqueuer enqueuer, Iterable<Element> elements) { 40 MirrorsHandler handler = forResolution ? resolutionHandler : codegenHandler;
40 MirrorsHandler handler = 41 handler.enqueueReflectiveStaticFields(elements);
41 enqueuer.isResolutionQueue ? resolutionHandler : codegenHandler; 42 return handler.flush();
42 handler.enqueueReflectiveStaticFields(enqueuer, elements);
43 } 43 }
44 } 44 }
45 45
46 class MirrorsHandler { 46 class MirrorsHandler {
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 final JavaScriptBackend _backend; 50 final JavaScriptBackend _backend;
51 final Resolution _resolution; 51 final Resolution _resolution;
52 52
53 bool hasEnqueuedReflectiveElements = false; 53 bool hasEnqueuedReflectiveElements = false;
54 bool hasEnqueuedReflectiveStaticFields = false; 54 bool hasEnqueuedReflectiveStaticFields = false;
55 55
56 StagedWorldImpactBuilder impactBuilder = new StagedWorldImpactBuilder();
57
56 MirrorsHandler(this._backend, this._resolution); 58 MirrorsHandler(this._backend, this._resolution);
57 59
58 DiagnosticReporter get _reporter => _resolution.reporter; 60 DiagnosticReporter get _reporter => _resolution.reporter;
59 61
62 WorldImpact flush() => impactBuilder.flush();
63
60 void _logEnqueueReflectiveAction(action, [msg = ""]) { 64 void _logEnqueueReflectiveAction(action, [msg = ""]) {
61 if (TRACE_MIRROR_ENQUEUING) { 65 if (TRACE_MIRROR_ENQUEUING) {
62 print("MIRROR_ENQUEUE (R): $action $msg"); 66 print("MIRROR_ENQUEUE (R): $action $msg");
63 } 67 }
64 } 68 }
65 69
66 /** 70 /**
67 * Decides whether an element should be included to satisfy requirements 71 * Decides whether an element should be included to satisfy requirements
68 * of the mirror system. 72 * of the mirror system.
69 * 73 *
70 * During resolution, we have to resort to matching elements against the 74 * During resolution, we have to resort to matching elements against the
71 * [MirrorsUsed] pattern, as we do not have a complete picture of the world, 75 * [MirrorsUsed] pattern, as we do not have a complete picture of the world,
72 * yet. 76 * yet.
73 */ 77 */
74 bool _shouldIncludeElementDueToMirrors(Element element, 78 bool _shouldIncludeElementDueToMirrors(Element element,
75 {bool includedEnclosing}) { 79 {bool includedEnclosing}) {
76 return includedEnclosing || _backend.requiredByMirrorSystem(element); 80 return includedEnclosing || _backend.requiredByMirrorSystem(element);
77 } 81 }
78 82
79 /// Enqeue the constructor [ctor] if it is required for reflection. 83 /// Enqeue the constructor [ctor] if it is required for reflection.
80 /// 84 ///
81 /// [enclosingWasIncluded] provides a hint whether the enclosing element was 85 /// [enclosingWasIncluded] provides a hint whether the enclosing element was
82 /// needed for reflection. 86 /// needed for reflection.
83 void _enqueueReflectiveConstructor( 87 void _enqueueReflectiveConstructor(ConstructorElement constructor,
84 Enqueuer enqueuer, ConstructorElement constructor,
85 {bool enclosingWasIncluded}) { 88 {bool enclosingWasIncluded}) {
86 if (_shouldIncludeElementDueToMirrors(constructor, 89 if (_shouldIncludeElementDueToMirrors(constructor,
87 includedEnclosing: enclosingWasIncluded)) { 90 includedEnclosing: enclosingWasIncluded)) {
88 _logEnqueueReflectiveAction(constructor); 91 _logEnqueueReflectiveAction(constructor);
89 ClassElement cls = constructor.declaration.enclosingClass; 92 ClassElement cls = constructor.declaration.enclosingClass;
90 enqueuer.registerTypeUse(new TypeUse.mirrorInstantiation(cls.rawType)); 93 impactBuilder
91 enqueuer 94 .registerTypeUse(new TypeUse.mirrorInstantiation(cls.rawType));
95 impactBuilder
92 .registerStaticUse(new StaticUse.foreignUse(constructor.declaration)); 96 .registerStaticUse(new StaticUse.foreignUse(constructor.declaration));
93 } 97 }
94 } 98 }
95 99
96 /// Enqeue the member [element] if it is required for reflection. 100 /// Enqeue the member [element] if it is required for reflection.
97 /// 101 ///
98 /// [enclosingWasIncluded] provides a hint whether the enclosing element was 102 /// [enclosingWasIncluded] provides a hint whether the enclosing element was
99 /// needed for reflection. 103 /// needed for reflection.
100 void _enqueueReflectiveMember( 104 void _enqueueReflectiveMember(Element element, bool enclosingWasIncluded) {
101 Enqueuer enqueuer, Element element, bool enclosingWasIncluded) {
102 if (_shouldIncludeElementDueToMirrors(element, 105 if (_shouldIncludeElementDueToMirrors(element,
103 includedEnclosing: enclosingWasIncluded)) { 106 includedEnclosing: enclosingWasIncluded)) {
104 _logEnqueueReflectiveAction(element); 107 _logEnqueueReflectiveAction(element);
105 if (element.isTypedef) { 108 if (element.isTypedef) {
106 TypedefElement typedef = element; 109 TypedefElement typedef = element;
107 typedef.ensureResolved(_resolution); 110 typedef.ensureResolved(_resolution);
108 } else if (Elements.isStaticOrTopLevel(element)) { 111 } else if (Elements.isStaticOrTopLevel(element)) {
109 enqueuer 112 impactBuilder
110 .registerStaticUse(new StaticUse.foreignUse(element.declaration)); 113 .registerStaticUse(new StaticUse.foreignUse(element.declaration));
111 } else if (element.isInstanceMember) { 114 } else if (element.isInstanceMember) {
112 // We need to enqueue all members matching this one in subclasses, as 115 // We need to enqueue all members matching this one in subclasses, as
113 // well. 116 // well.
114 // TODO(herhut): Use TypedSelector.subtype for enqueueing 117 // TODO(herhut): Use TypedSelector.subtype for enqueueing
115 DynamicUse dynamicUse = 118 DynamicUse dynamicUse =
116 new DynamicUse(new Selector.fromElement(element), null); 119 new DynamicUse(new Selector.fromElement(element), null);
117 enqueuer.registerDynamicUse(dynamicUse); 120 impactBuilder.registerDynamicUse(dynamicUse);
118 if (element.isField) { 121 if (element.isField) {
119 DynamicUse dynamicUse = new DynamicUse( 122 DynamicUse dynamicUse = new DynamicUse(
120 new Selector.setter( 123 new Selector.setter(
121 new Name(element.name, element.library, isSetter: true)), 124 new Name(element.name, element.library, isSetter: true)),
122 null); 125 null);
123 enqueuer.registerDynamicUse(dynamicUse); 126 impactBuilder.registerDynamicUse(dynamicUse);
124 } 127 }
125 } 128 }
126 } 129 }
127 } 130 }
128 131
129 /// Enqeue the member [element] if it is required for reflection. 132 /// Enqeue the member [element] if it is required for reflection.
130 /// 133 ///
131 /// [enclosingWasIncluded] provides a hint whether the enclosing element was 134 /// [enclosingWasIncluded] provides a hint whether the enclosing element was
132 /// needed for reflection. 135 /// needed for reflection.
133 void _enqueueReflectiveElementsInClass( 136 void _enqueueReflectiveElementsInClass(
134 Enqueuer enqueuer, ClassElement cls, Iterable<ClassElement> recents, 137 ClassElement cls, Iterable<ClassElement> recents,
135 {bool enclosingWasIncluded}) { 138 {bool enclosingWasIncluded}) {
136 if (cls.library.isInternalLibrary || cls.isInjected) return; 139 if (cls.library.isInternalLibrary || cls.isInjected) return;
137 bool includeClass = _shouldIncludeElementDueToMirrors(cls, 140 bool includeClass = _shouldIncludeElementDueToMirrors(cls,
138 includedEnclosing: enclosingWasIncluded); 141 includedEnclosing: enclosingWasIncluded);
139 if (includeClass) { 142 if (includeClass) {
140 _logEnqueueReflectiveAction(cls, "register"); 143 _logEnqueueReflectiveAction(cls, "register");
141 ClassElement declaration = cls.declaration; 144 ClassElement declaration = cls.declaration;
142 declaration.ensureResolved(_resolution); 145 declaration.ensureResolved(_resolution);
143 enqueuer.registerTypeUse( 146 impactBuilder.registerTypeUse(
144 new TypeUse.mirrorInstantiation(declaration.rawType)); 147 new TypeUse.mirrorInstantiation(declaration.rawType));
145 } 148 }
146 // If the class is never instantiated, we know nothing of it can possibly 149 // If the class is never instantiated, we know nothing of it can possibly
147 // be reflected upon. 150 // be reflected upon.
148 // TODO(herhut): Add a warning if a mirrors annotation cannot hit. 151 // TODO(herhut): Add a warning if a mirrors annotation cannot hit.
149 if (recents.contains(cls.declaration)) { 152 if (recents.contains(cls.declaration)) {
150 _logEnqueueReflectiveAction(cls, "members"); 153 _logEnqueueReflectiveAction(cls, "members");
151 cls.constructors.forEach((Element element) { 154 cls.constructors.forEach((Element element) {
152 _enqueueReflectiveConstructor(enqueuer, element, 155 _enqueueReflectiveConstructor(element,
153 enclosingWasIncluded: includeClass); 156 enclosingWasIncluded: includeClass);
154 }); 157 });
155 cls.forEachClassMember((Member member) { 158 cls.forEachClassMember((Member member) {
156 _enqueueReflectiveMember(enqueuer, member.element, includeClass); 159 _enqueueReflectiveMember(member.element, includeClass);
157 }); 160 });
158 } 161 }
159 } 162 }
160 163
161 /// Enqeue special classes that might not be visible by normal means or that 164 /// Enqeue special classes that might not be visible by normal means or that
162 /// would not normally be enqueued: 165 /// would not normally be enqueued:
163 /// 166 ///
164 /// [Closure] is treated specially as it is the superclass of all closures. 167 /// [Closure] is treated specially as it is the superclass of all closures.
165 /// Although it is in an internal library, we mark it as reflectable. Note 168 /// Although it is in an internal library, we mark it as reflectable. Note
166 /// that none of its methods are reflectable, unless reflectable by 169 /// that none of its methods are reflectable, unless reflectable by
167 /// inheritance. 170 /// inheritance.
168 void _enqueueReflectiveSpecialClasses(Enqueuer enqueuer) { 171 void _enqueueReflectiveSpecialClasses() {
169 Iterable<ClassElement> classes = _backend.classesRequiredForReflection; 172 Iterable<ClassElement> classes = _backend.classesRequiredForReflection;
170 for (ClassElement cls in classes) { 173 for (ClassElement cls in classes) {
171 if (_backend.referencedFromMirrorSystem(cls)) { 174 if (_backend.referencedFromMirrorSystem(cls)) {
172 _logEnqueueReflectiveAction(cls); 175 _logEnqueueReflectiveAction(cls);
173 cls.ensureResolved(_resolution); 176 cls.ensureResolved(_resolution);
174 enqueuer.registerTypeUse(new TypeUse.mirrorInstantiation(cls.rawType)); 177 impactBuilder
178 .registerTypeUse(new TypeUse.mirrorInstantiation(cls.rawType));
175 } 179 }
176 } 180 }
177 } 181 }
178 182
179 /// Enqeue all local members of the library [lib] if they are required for 183 /// Enqeue all local members of the library [lib] if they are required for
180 /// reflection. 184 /// reflection.
181 void _enqueueReflectiveElementsInLibrary( 185 void _enqueueReflectiveElementsInLibrary(
182 Enqueuer enqueuer, LibraryElement lib, Iterable<ClassElement> recents) { 186 LibraryElement lib, Iterable<ClassElement> recents) {
183 bool includeLibrary = 187 bool includeLibrary =
184 _shouldIncludeElementDueToMirrors(lib, includedEnclosing: false); 188 _shouldIncludeElementDueToMirrors(lib, includedEnclosing: false);
185 lib.forEachLocalMember((Element member) { 189 lib.forEachLocalMember((Element member) {
186 if (member.isInjected) return; 190 if (member.isInjected) return;
187 if (member.isClass) { 191 if (member.isClass) {
188 _enqueueReflectiveElementsInClass(enqueuer, member, recents, 192 _enqueueReflectiveElementsInClass(member, recents,
189 enclosingWasIncluded: includeLibrary); 193 enclosingWasIncluded: includeLibrary);
190 } else { 194 } else {
191 _enqueueReflectiveMember(enqueuer, member, includeLibrary); 195 _enqueueReflectiveMember(member, includeLibrary);
192 } 196 }
193 }); 197 });
194 } 198 }
195 199
196 /// Enqueue all elements that are matched by the mirrors used 200 /// Enqueue all elements that are matched by the mirrors used
197 /// annotation or, in lack thereof, all elements. 201 /// annotation or, in lack thereof, all elements.
198 // TODO(johnniwinther): Compute [WorldImpact] instead of enqueuing directly. 202 // TODO(johnniwinther): Compute [WorldImpact] instead of enqueuing directly.
199 void enqueueReflectiveElements( 203 void enqueueReflectiveElements(
200 Enqueuer enqueuer,
201 Iterable<ClassElement> recents, 204 Iterable<ClassElement> recents,
205 Iterable<ClassElement> processedClasses,
202 Iterable<LibraryElement> loadedLibraries) { 206 Iterable<LibraryElement> loadedLibraries) {
203 if (!hasEnqueuedReflectiveElements) { 207 if (!hasEnqueuedReflectiveElements) {
204 _logEnqueueReflectiveAction("!START enqueueAll"); 208 _logEnqueueReflectiveAction("!START enqueueAll");
205 // First round of enqueuing, visit everything that is visible to 209 // First round of enqueuing, visit everything that is visible to
206 // also pick up static top levels, etc. 210 // also pick up static top levels, etc.
207 // Also, during the first round, consider all classes that have been seen 211 // Also, during the first round, consider all classes that have been seen
208 // as recently seen, as we do not know how many rounds of resolution might 212 // as recently seen, as we do not know how many rounds of resolution might
209 // have run before tree shaking is disabled and thus everything is 213 // have run before tree shaking is disabled and thus everything is
210 // enqueued. 214 // enqueued.
211 recents = enqueuer.processedClasses.toSet(); 215 recents = processedClasses.toSet();
212 _reporter.log('Enqueuing everything'); 216 _reporter.log('Enqueuing everything');
213 for (LibraryElement lib in loadedLibraries) { 217 for (LibraryElement lib in loadedLibraries) {
214 _enqueueReflectiveElementsInLibrary(enqueuer, lib, recents); 218 _enqueueReflectiveElementsInLibrary(lib, recents);
215 } 219 }
216 _enqueueReflectiveSpecialClasses(enqueuer); 220 _enqueueReflectiveSpecialClasses();
217 hasEnqueuedReflectiveElements = true; 221 hasEnqueuedReflectiveElements = true;
218 hasEnqueuedReflectiveStaticFields = true; 222 hasEnqueuedReflectiveStaticFields = true;
219 _logEnqueueReflectiveAction("!DONE enqueueAll"); 223 _logEnqueueReflectiveAction("!DONE enqueueAll");
220 } else if (recents.isNotEmpty) { 224 } else if (recents.isNotEmpty) {
221 // Keep looking at new classes until fixpoint is reached. 225 // Keep looking at new classes until fixpoint is reached.
222 _logEnqueueReflectiveAction("!START enqueueRecents"); 226 _logEnqueueReflectiveAction("!START enqueueRecents");
223 recents.forEach((ClassElement cls) { 227 recents.forEach((ClassElement cls) {
224 _enqueueReflectiveElementsInClass(enqueuer, cls, recents, 228 _enqueueReflectiveElementsInClass(cls, recents,
225 enclosingWasIncluded: _shouldIncludeElementDueToMirrors(cls.library, 229 enclosingWasIncluded: _shouldIncludeElementDueToMirrors(cls.library,
226 includedEnclosing: false)); 230 includedEnclosing: false));
227 }); 231 });
228 _logEnqueueReflectiveAction("!DONE enqueueRecents"); 232 _logEnqueueReflectiveAction("!DONE enqueueRecents");
229 } 233 }
230 } 234 }
231 235
232 /// Enqueue the static fields that have been marked as used by reflective 236 /// Enqueue the static fields that have been marked as used by reflective
233 /// usage through `MirrorsUsed`. 237 /// usage through `MirrorsUsed`.
234 // TODO(johnniwinther): Compute [WorldImpact] instead of enqueuing directly. 238 // TODO(johnniwinther): Compute [WorldImpact] instead of enqueuing directly.
235 void enqueueReflectiveStaticFields( 239 void enqueueReflectiveStaticFields(Iterable<Element> elements) {
236 Enqueuer enqueuer, Iterable<Element> elements) {
237 if (hasEnqueuedReflectiveStaticFields) return; 240 if (hasEnqueuedReflectiveStaticFields) return;
238 hasEnqueuedReflectiveStaticFields = true; 241 hasEnqueuedReflectiveStaticFields = true;
239 for (Element element in elements) { 242 for (Element element in elements) {
240 _enqueueReflectiveMember(enqueuer, element, true); 243 _enqueueReflectiveMember(element, true);
241 } 244 }
242 } 245 }
243 } 246 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend.dart ('k') | pkg/compiler/lib/src/types/types.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698