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

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

Issue 2748383003: Split MirrorsAnalysis (Closed)
Patch Set: Created 3 years, 9 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
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.dart'; 7 import '../common.dart';
8 import '../common/resolution.dart'; 8 import '../common/resolution.dart';
9 import '../compiler.dart'; 9 import '../compiler.dart';
10 import '../constants/values.dart'; 10 import '../constants/values.dart';
11 import '../diagnostics/diagnostic_listener.dart'; 11 import '../diagnostics/diagnostic_listener.dart';
12 import '../elements/elements.dart'; 12 import '../elements/elements.dart';
13 import '../elements/entities.dart'; 13 import '../elements/entities.dart';
14 import '../enqueue.dart'; 14 import '../enqueue.dart';
15 import '../universe/selector.dart'; 15 import '../universe/selector.dart';
16 import '../universe/use.dart'; 16 import '../universe/use.dart';
17 import '../universe/world_impact.dart'; 17 import '../universe/world_impact.dart';
18 import 'backend.dart'; 18 import 'backend.dart';
19 import 'constant_handler_javascript.dart'; 19 import 'constant_handler_javascript.dart';
20 import 'mirrors_data.dart'; 20 import 'mirrors_data.dart';
21 21
22 class MirrorsAnalysis { 22 abstract class MirrorsResolutionAnalysis {
23 final JavaScriptBackend backend; 23 void onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses);
24 final MirrorsHandler resolutionHandler;
25 final MirrorsHandler codegenHandler;
26 24
27 /// List of constants from metadata. If metadata must be preserved, 25 void onResolutionComplete();
28 /// these constants must be registered. 26
29 final List<Dependency> metadataConstants = <Dependency>[]; 27 /// Close this analysis and create the [MirrorsCodegenAnalysis] for the
28 /// collected data.
29 MirrorsCodegenAnalysis close();
30 }
31
32 abstract class MirrorsCodegenAnalysis {
33 void onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses);
34
35 /// Number of methods compiled before considering reflection.
36 int get preMirrorsMethodCount;
37 }
38
39 class MirrorsResolutionAnalysisImpl implements MirrorsResolutionAnalysis {
40 final JavaScriptBackend _backend;
41 final MirrorsHandler handler;
30 42
31 /// Set of elements for which metadata has been registered as dependencies. 43 /// Set of elements for which metadata has been registered as dependencies.
32 final Set<Element> _registeredMetadata = new Set<Element>(); 44 final Set<Element> _registeredMetadata = new Set<Element>();
33 45
34 StagedWorldImpactBuilder constantImpactsForResolution = 46 /// List of constants from metadata. If metadata must be preserved,
35 new StagedWorldImpactBuilder(); 47 /// these constants must be registered.
48 final List<Dependency> _metadataConstants = <Dependency>[];
36 49
37 StagedWorldImpactBuilder constantImpactsForCodegen = 50 StagedWorldImpactBuilder _impactBuilder = new StagedWorldImpactBuilder();
38 new StagedWorldImpactBuilder();
39 51
40 /// Number of methods compiled before considering reflection. 52 MirrorsResolutionAnalysisImpl(this._backend, Resolution resolution)
41 int preMirrorsMethodCount = 0; 53 : handler = new MirrorsHandler(_backend, resolution);
42 54
43 MirrorsAnalysis(this.backend, Resolution resolution) 55 DiagnosticReporter get _reporter => _backend.reporter;
44 : resolutionHandler = new MirrorsHandler(backend, resolution), 56 Compiler get _compiler => _backend.compiler;
45 codegenHandler = new MirrorsHandler(backend, resolution); 57 JavaScriptConstantCompiler get _constants => _backend.constants;
46 58 MirrorsData get _mirrorsData => _backend.mirrorsData;
47 DiagnosticReporter get reporter => backend.reporter;
48 Compiler get compiler => backend.compiler;
49 JavaScriptConstantCompiler get constants => backend.constants;
50 MirrorsData get mirrorsData => backend.mirrorsData;
51 59
52 /// Returns all static fields that are referenced through 60 /// Returns all static fields that are referenced through
53 /// `mirrorsData.targetsUsed`. If the target is a library or class all nested 61 /// `mirrorsData.targetsUsed`. If the target is a library or class all nested
54 /// static fields are included too. 62 /// static fields are included too.
55 Iterable<Element> _findStaticFieldTargets() { 63 Iterable<Element> _findStaticFieldTargets() {
56 List staticFields = []; 64 List staticFields = [];
57 65
58 void addFieldsInContainer(ScopeContainerElement container) { 66 void addFieldsInContainer(ScopeContainerElement container) {
59 container.forEachLocalMember((Element member) { 67 container.forEachLocalMember((Element member) {
60 if (!member.isInstanceMember && member.isField) { 68 if (!member.isInstanceMember && member.isField) {
61 staticFields.add(member); 69 staticFields.add(member);
62 } else if (member.isClass) { 70 } else if (member.isClass) {
63 addFieldsInContainer(member); 71 addFieldsInContainer(member);
64 } 72 }
65 }); 73 });
66 } 74 }
67 75
68 for (Element target in mirrorsData.targetsUsed) { 76 for (Element target in _mirrorsData.targetsUsed) {
69 if (target == null) continue; 77 if (target == null) continue;
70 if (target.isField) { 78 if (target.isField) {
71 staticFields.add(target); 79 staticFields.add(target);
72 } else if (target.isLibrary || target.isClass) { 80 } else if (target.isLibrary || target.isClass) {
73 addFieldsInContainer(target); 81 addFieldsInContainer(target);
74 } 82 }
75 } 83 }
76 return staticFields; 84 return staticFields;
77 } 85 }
78 86
87 /// Compute the impact for elements that are matched by the mirrors used
88 /// annotation or, in lack thereof, all elements.
89 WorldImpact _computeImpactForReflectiveElements(
90 Iterable<ClassEntity> recents,
91 Iterable<ClassEntity> processedClasses,
92 Iterable<LibraryElement> loadedLibraries) {
93 handler.enqueueReflectiveElements(
94 recents, processedClasses, loadedLibraries);
95 return handler.flush();
96 }
97
98 /// Compute the impact for the static fields that have been marked as used by
99 /// reflective usage through `MirrorsUsed`.
100 WorldImpact _computeImpactForReflectiveStaticFields(
101 Iterable<Element> elements) {
102 handler.enqueueReflectiveStaticFields(elements);
103 return handler.flush();
104 }
105
106 void onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses) {
107 if (_mirrorsData.isTreeShakingDisabled) {
108 enqueuer.applyImpact(_computeImpactForReflectiveElements(recentClasses,
109 enqueuer.processedClasses, _compiler.libraryLoader.libraries));
110 } else if (!_mirrorsData.targetsUsed.isEmpty) {
111 // Add all static elements (not classes) that have been requested for
112 // reflection. If there is no mirror-usage these are probably not
113 // necessary, but the backend relies on them being resolved.
114 enqueuer.applyImpact(
115 _computeImpactForReflectiveStaticFields(_findStaticFieldTargets()));
116 }
117
118 if (_mirrorsData.mustPreserveNames) _reporter.log('Preserving names.');
119
120 if (_mirrorsData.mustRetainMetadata) {
121 _reporter.log('Retaining metadata.');
122
123 _compiler.libraryLoader.libraries.forEach(_mirrorsData.retainMetadataOf);
124
125 if (!enqueuer.queueIsClosed) {
126 /// Register the constant value of [metadata] as live in resolution.
127 void registerMetadataConstant(MetadataAnnotation metadata) {
128 ConstantValue constant =
129 _constants.getConstantValueForMetadata(metadata);
130 Dependency dependency =
131 new Dependency(constant, metadata.annotatedElement);
132 _metadataConstants.add(dependency);
133 _impactBuilder.registerConstantUse(new ConstantUse.mirrors(constant));
134 }
135
136 // TODO(johnniwinther): We should have access to all recently processed
137 // elements and process these instead.
138 processMetadata(enqueuer.processedEntities, registerMetadataConstant);
139 } else {
140 for (Dependency dependency in _metadataConstants) {
141 _impactBuilder.registerConstantUse(
142 new ConstantUse.mirrors(dependency.constant));
143 }
144 _metadataConstants.clear();
145 }
146 enqueuer.applyImpact(_impactBuilder.flush());
147 }
148 }
149
79 /// Call [registerMetadataConstant] on all metadata from [entities]. 150 /// Call [registerMetadataConstant] on all metadata from [entities].
80 void processMetadata( 151 void processMetadata(
81 Iterable<Entity> entities, void onMetadata(MetadataAnnotation metadata)) { 152 Iterable<Entity> entities, void onMetadata(MetadataAnnotation metadata)) {
82 void processLibraryMetadata(LibraryElement library) { 153 void processLibraryMetadata(LibraryElement library) {
83 if (_registeredMetadata.add(library)) { 154 if (_registeredMetadata.add(library)) {
84 library.metadata.forEach(onMetadata); 155 library.metadata.forEach(onMetadata);
85 library.entryCompilationUnit.metadata.forEach(onMetadata); 156 library.entryCompilationUnit.metadata.forEach(onMetadata);
86 for (ImportElement import in library.imports) { 157 for (ImportElement import in library.imports) {
87 import.metadata.forEach(onMetadata); 158 import.metadata.forEach(onMetadata);
88 } 159 }
(...skipping 21 matching lines...) Expand all
110 } 181 }
111 } else { 182 } else {
112 processLibraryMetadata(element.library); 183 processLibraryMetadata(element.library);
113 } 184 }
114 } 185 }
115 } 186 }
116 187
117 entities.forEach(processElementMetadata); 188 entities.forEach(processElementMetadata);
118 } 189 }
119 190
120 void onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses) {
121 if (!enqueuer.isResolutionQueue && preMirrorsMethodCount == 0) {
122 preMirrorsMethodCount = backend.generatedCode.length;
123 }
124 if (mirrorsData.isTreeShakingDisabled) {
125 enqueuer.applyImpact(_computeImpactForReflectiveElements(recentClasses,
126 enqueuer.processedClasses, compiler.libraryLoader.libraries,
127 forResolution: enqueuer.isResolutionQueue));
128 } else if (!mirrorsData.targetsUsed.isEmpty && enqueuer.isResolutionQueue) {
129 // Add all static elements (not classes) that have been requested for
130 // reflection. If there is no mirror-usage these are probably not
131 // necessary, but the backend relies on them being resolved.
132 enqueuer.applyImpact(
133 _computeImpactForReflectiveStaticFields(_findStaticFieldTargets()));
134 }
135
136 if (mirrorsData.mustPreserveNames) reporter.log('Preserving names.');
137
138 if (mirrorsData.mustRetainMetadata) {
139 reporter.log('Retaining metadata.');
140
141 compiler.libraryLoader.libraries.forEach(mirrorsData.retainMetadataOf);
142
143 StagedWorldImpactBuilder impactBuilder = enqueuer.isResolutionQueue
144 ? constantImpactsForResolution
145 : constantImpactsForCodegen;
146 if (enqueuer.isResolutionQueue && !enqueuer.queueIsClosed) {
147 /// Register the constant value of [metadata] as live in resolution.
148 void registerMetadataConstant(MetadataAnnotation metadata) {
149 ConstantValue constant =
150 constants.getConstantValueForMetadata(metadata);
151 Dependency dependency =
152 new Dependency(constant, metadata.annotatedElement);
153 metadataConstants.add(dependency);
154 impactBuilder.registerConstantUse(new ConstantUse.mirrors(constant));
155 }
156
157 // TODO(johnniwinther): We should have access to all recently processed
158 // elements and process these instead.
159 processMetadata(enqueuer.processedEntities, registerMetadataConstant);
160 } else {
161 for (Dependency dependency in metadataConstants) {
162 impactBuilder.registerConstantUse(
163 new ConstantUse.mirrors(dependency.constant));
164 }
165 metadataConstants.clear();
166 }
167 enqueuer.applyImpact(impactBuilder.flush());
168 }
169 }
170
171 void onResolutionComplete() { 191 void onResolutionComplete() {
172 _registeredMetadata.clear(); 192 _registeredMetadata.clear();
173 } 193 }
174 194
195 MirrorsCodegenAnalysis close() => new MirrorsCodegenAnalysisImpl(
196 _backend, handler._resolution, _metadataConstants);
197 }
198
199 class MirrorsCodegenAnalysisImpl implements MirrorsCodegenAnalysis {
200 final JavaScriptBackend _backend;
201 final MirrorsHandler handler;
202
203 StagedWorldImpactBuilder _impactBuilder = new StagedWorldImpactBuilder();
204
205 /// List of constants from metadata. If metadata must be preserved,
206 /// these constants must be registered.
207 final List<Dependency> _metadataConstants;
208
209 /// Number of methods compiled before considering reflection.
210 int preMirrorsMethodCount = 0;
211
212 MirrorsCodegenAnalysisImpl(
213 this._backend, Resolution resolution, this._metadataConstants)
214 : handler = new MirrorsHandler(_backend, resolution);
215
216 DiagnosticReporter get _reporter => _backend.reporter;
217 Compiler get _compiler => _backend.compiler;
218 JavaScriptConstantCompiler get _constants => _backend.constants;
219 MirrorsData get _mirrorsData => _backend.mirrorsData;
220
175 /// Compute the impact for elements that are matched by the mirrors used 221 /// Compute the impact for elements that are matched by the mirrors used
176 /// annotation or, in lack thereof, all elements. 222 /// annotation or, in lack thereof, all elements.
177 WorldImpact _computeImpactForReflectiveElements( 223 WorldImpact _computeImpactForReflectiveElements(
178 Iterable<ClassEntity> recents, 224 Iterable<ClassEntity> recents,
179 Iterable<ClassEntity> processedClasses, 225 Iterable<ClassEntity> processedClasses,
180 Iterable<LibraryElement> loadedLibraries, 226 Iterable<LibraryElement> loadedLibraries) {
181 {bool forResolution}) {
182 MirrorsHandler handler = forResolution ? resolutionHandler : codegenHandler;
183 handler.enqueueReflectiveElements( 227 handler.enqueueReflectiveElements(
184 recents, processedClasses, loadedLibraries); 228 recents, processedClasses, loadedLibraries);
185 return handler.flush(); 229 return handler.flush();
186 } 230 }
187 231
188 /// Compute the impact for the static fields that have been marked as used by 232 void onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses) {
189 /// reflective usage through `MirrorsUsed`. 233 if (preMirrorsMethodCount == 0) {
190 WorldImpact _computeImpactForReflectiveStaticFields( 234 preMirrorsMethodCount = _backend.generatedCode.length;
191 Iterable<Element> elements) { 235 }
192 resolutionHandler.enqueueReflectiveStaticFields(elements); 236 if (_mirrorsData.isTreeShakingDisabled) {
193 return resolutionHandler.flush(); 237 enqueuer.applyImpact(_computeImpactForReflectiveElements(recentClasses,
238 enqueuer.processedClasses, _compiler.libraryLoader.libraries));
239 }
240
241 if (_mirrorsData.mustPreserveNames) _reporter.log('Preserving names.');
242
243 if (_mirrorsData.mustRetainMetadata) {
244 _reporter.log('Retaining metadata.');
245
246 _compiler.libraryLoader.libraries.forEach(_mirrorsData.retainMetadataOf);
247
248 for (Dependency dependency in _metadataConstants) {
249 _impactBuilder
250 .registerConstantUse(new ConstantUse.mirrors(dependency.constant));
251 }
252 _metadataConstants.clear();
253 enqueuer.applyImpact(_impactBuilder.flush());
254 }
194 } 255 }
195 } 256 }
196 257
197 class MirrorsHandler { 258 class MirrorsHandler {
198 static final TRACE_MIRROR_ENQUEUING = 259 static final TRACE_MIRROR_ENQUEUING =
199 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); 260 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING");
200 261
201 final JavaScriptBackend _backend; 262 final JavaScriptBackend _backend;
202 final Resolution _resolution; 263 final Resolution _resolution;
203 264
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 468
408 /// Records that [constant] is used by the element behind [registry]. 469 /// Records that [constant] is used by the element behind [registry].
409 class Dependency { 470 class Dependency {
410 final ConstantValue constant; 471 final ConstantValue constant;
411 final Element annotatedElement; 472 final Element annotatedElement;
412 473
413 const Dependency(this.constant, this.annotatedElement); 474 const Dependency(this.constant, this.annotatedElement);
414 475
415 String toString() => '$annotatedElement:${constant.toStructuredText()}'; 476 String toString() => '$annotatedElement:${constant.toStructuredText()}';
416 } 477 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/codegen_listener.dart ('k') | pkg/compiler/lib/src/js_backend/resolution_listener.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698