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

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

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

Powered by Google App Engine
This is Rietveld 408576698