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

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

Issue 2791263005: Split MirrorsData methods and MirrorsDataImpl data by element kind. (Closed)
Patch Set: Updated cf. comments. Created 3 years, 8 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) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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 import '../closure.dart'; 5 import '../closure.dart';
6 import '../common.dart'; 6 import '../common.dart';
7 import '../common_elements.dart'; 7 import '../common_elements.dart';
8 import '../compiler.dart'; 8 import '../compiler.dart';
9 import '../constants/values.dart'; 9 import '../constants/values.dart';
10 import '../elements/elements.dart'; 10 import '../elements/elements.dart';
11 import '../elements/resolution_types.dart'; 11 import '../elements/entities.dart';
12 import '../elements/types.dart';
12 import '../options.dart'; 13 import '../options.dart';
13 import '../world.dart'; 14 import '../world.dart';
14 import '../universe/world_builder.dart'; 15 import '../universe/world_builder.dart';
15 import '../util/emptyset.dart'; 16 import '../util/emptyset.dart';
16 import 'backend_helpers.dart'; 17 import 'backend_helpers.dart';
17 import 'constant_handler_javascript.dart'; 18 import 'constant_handler_javascript.dart';
18 19
19 abstract class MirrorsData { 20 abstract class MirrorsData {
20 /// True if a call to preserveMetadataMarker has been seen. This means that 21 /// True if a call to preserveMetadataMarker has been seen. This means that
21 /// metadata must be retained for dart:mirrors to work correctly. 22 /// metadata must be retained for dart:mirrors to work correctly.
(...skipping 18 matching lines...) Expand all
40 /// True if a call to disableTreeShaking has been seen. 41 /// True if a call to disableTreeShaking has been seen.
41 bool get isTreeShakingDisabled; 42 bool get isTreeShakingDisabled;
42 43
43 /// True if a call to preserveUris has been seen and the preserve-uris flag 44 /// True if a call to preserveUris has been seen and the preserve-uris flag
44 /// is set. 45 /// is set.
45 bool get mustPreserveUris; 46 bool get mustPreserveUris;
46 47
47 /// Set of symbols that the user has requested for reflection. 48 /// Set of symbols that the user has requested for reflection.
48 Iterable<String> get symbolsUsed; 49 Iterable<String> get symbolsUsed;
49 50
50 /// Set of elements that the user has requested for reflection. 51 /// The members that the user has requested for reflection through the
51 Iterable<Element> get targetsUsed; 52 /// 'targets' property of a `MirrorsUsed` annotation.
53 Iterable<MemberEntity> get membersInMirrorsUsedTargets;
52 54
53 /// Should [element] (a getter) that would normally not be generated due to 55 /// The classes that the user has requested for reflection through the
54 /// treeshaking be retained for reflection? 56 /// 'targets' property of a `MirrorsUsed` annotation.
55 bool shouldRetainGetter(Element element); 57 Iterable<ClassEntity> get classesInMirrorsUsedTargets;
56 58
57 /// Should [element] (a setter) hat would normally not be generated due to 59 /// The libraries that the user has requested for reflection through the
58 /// treeshaking be retained for reflection? 60 /// 'targets' property of a `MirrorsUsed` annotation.
59 bool shouldRetainSetter(Element element); 61 Iterable<LibraryEntity> get librariesInMirrorsUsedTargets;
62
63 /// Should the getter for [element] that would normally not be generated due
64 /// to tree-shaking be retained for reflection?
65 bool shouldRetainGetter(FieldEntity element);
66
67 /// Should the setter for [element] that would normally not be generated due
68 /// to tree-shaking be retained for reflection?
69 bool shouldRetainSetter(FieldEntity element);
60 70
61 /// Should [name] be retained for reflection? 71 /// Should [name] be retained for reflection?
62 bool shouldRetainName(String name); 72 bool shouldRetainName(String name);
63 73
64 /// Returns true if this element is covered by a mirrorsUsed annotation. 74 /// Returns `true` if the class [element] is covered by a `MirrorsUsed`
75 /// annotation.
65 /// 76 ///
66 /// Note that it might still be ok to tree shake the element away if no 77 /// Note that it might still be ok to tree shake the element away if no
67 /// reflection is used in the program (and thus [isTreeShakingDisabled] is 78 /// reflection is used in the program (and thus [isTreeShakingDisabled] is
68 /// still false). Therefore _do not_ use this predicate to decide inclusion 79 /// still false). Therefore _do not_ use this predicate to decide inclusion
69 /// in the tree, use [requiredByMirrorSystem] instead. 80 /// in the tree, use [requiredByMirrorSystem] instead.
70 bool referencedFromMirrorSystem(Element element, [recursive = true]); 81 bool isClassReferencedFromMirrorSystem(ClassEntity element);
71 82
72 /// Returns `true` if [element] can be accessed through reflection, that is, 83 /// Returns `true` if the member [element] is covered by a `MirrorsUsed`
73 /// is in the set of elements covered by a `MirrorsUsed` annotation. 84 /// annotation.
85 ///
86 /// Note that it might still be ok to tree shake the element away if no
87 /// reflection is used in the program (and thus [isTreeShakingDisabled] is
88 /// still false). Therefore _do not_ use this predicate to decide inclusion
89 /// in the tree, use [requiredByMirrorSystem] instead.
90 bool isMemberReferencedFromMirrorSystem(MemberEntity element);
91
92 /// Returns `true` if the library [element] is covered by a `MirrorsUsed`
93 /// annotation.
94 bool isLibraryReferencedFromMirrorSystem(LibraryEntity element);
95
96 /// Returns `true` if the typedef [element] needs reflection information at
97 /// runtime.
74 /// 98 ///
75 /// This property is used to tag emitted elements with a marker which is 99 /// This property is used to tag emitted elements with a marker which is
76 /// checked by the runtime system to throw an exception if an element is 100 /// checked by the runtime system to throw an exception if an element is
77 /// accessed (invoked, get, set) that is not accessible for the reflective 101 /// accessed (invoked, get, set) that is not accessible for the reflective
78 /// system. 102 /// system.
103 bool isTypedefAccessibleByReflection(TypedefElement element);
104
105 /// Returns `true` if the class [element] needs reflection information at
106 /// runtime.
107 ///
108 /// This property is used to tag emitted elements with a marker which is
109 /// checked by the runtime system to throw an exception if an element is
110 /// accessed (invoked, get, set) that is not accessible for the reflective
111 /// system.
112 bool isClassAccessibleByReflection(ClassEntity element);
113
114 /// Returns `true` if the member [element] needs reflection information at
115 /// runtime.
116 ///
117 /// This property is used to tag emitted elements with a marker which is
118 /// checked by the runtime system to throw an exception if an element is
119 /// accessed (invoked, get, set) that is not accessible for the reflective
120 /// system.
121 bool isMemberAccessibleByReflection(MemberEntity element);
122
123 // TODO(johnniwinther): Remove this.
124 @deprecated
79 bool isAccessibleByReflection(Element element); 125 bool isAccessibleByReflection(Element element);
80 126
81 bool retainMetadataOf(Element element); 127 bool retainMetadataOfLibrary(LibraryEntity element);
128 bool retainMetadataOfTypedef(TypedefElement element);
129 bool retainMetadataOfClass(ClassEntity element);
130 bool retainMetadataOfMember(MemberEntity element);
131 bool retainMetadataOfParameter(ParameterElement element);
82 132
83 bool invokedReflectively(Element element); 133 bool invokedReflectively(Element element);
84 134
85 /// Returns `true` if this member element needs reflection information at
86 /// runtime.
87 bool isMemberAccessibleByReflection(MemberElement element);
88
89 /// Returns true if this element has to be enqueued due to 135 /// Returns true if this element has to be enqueued due to
90 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if 136 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if
91 /// normal tree shaking is still active ([isTreeShakingDisabled] is false). 137 /// normal tree shaking is still active ([isTreeShakingDisabled] is false).
92 bool requiredByMirrorSystem(Element element); 138 bool requiredByMirrorSystem(Element element);
93 } 139 }
94 140
95 abstract class MirrorsDataBuilder { 141 abstract class MirrorsDataBuilder {
96 void registerUsedMember(MemberElement member); 142 void registerUsedMember(MemberElement member);
97 143
98 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed 144 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 bool hasInsufficientMirrorsUsed = false; 183 bool hasInsufficientMirrorsUsed = false;
138 184
139 /// True if a call to preserveUris has been seen and the preserve-uris flag 185 /// True if a call to preserveUris has been seen and the preserve-uris flag
140 /// is set. 186 /// is set.
141 bool mustPreserveUris = false; 187 bool mustPreserveUris = false;
142 188
143 /// Set of symbols that the user has requested for reflection. 189 /// Set of symbols that the user has requested for reflection.
144 final Set<String> symbolsUsed = new Set<String>(); 190 final Set<String> symbolsUsed = new Set<String>();
145 191
146 /// Set of elements that the user has requested for reflection. 192 /// Set of elements that the user has requested for reflection.
147 final Set<Element> targetsUsed = new Set<Element>(); 193 final Set<MemberEntity> membersInMirrorsUsedTargets = new Set<MemberEntity>();
194 final Set<ClassEntity> classesInMirrorsUsedTargets = new Set<ClassEntity>();
195 final Set<LibraryEntity> librariesInMirrorsUsedTargets =
196 new Set<LibraryEntity>();
197 final Set<TypedefElement> _typedefsInMirrorsUsedTargets =
198 new Set<TypedefElement>();
148 199
149 /// List of annotations provided by user that indicate that the annotated 200 /// List of annotations provided by user that indicate that the annotated
150 /// element must be retained. 201 /// element must be retained.
151 final Set<Element> metaTargetsUsed = new Set<Element>(); 202 final Set<ClassEntity> metaTargetsUsed = new Set<ClassEntity>();
152 203
153 // TODO(johnniwinther): Avoid the need for this. 204 // TODO(johnniwinther): Avoid the need for this.
154 final Compiler _compiler; 205 final Compiler _compiler;
155 206
156 final CompilerOptions _options; 207 final CompilerOptions _options;
157 208
158 final CommonElements _commonElements; 209 final CommonElements _commonElements;
159 210
160 final BackendHelpers _helpers; 211 final BackendHelpers _helpers;
161 212
162 final JavaScriptConstantCompiler _constants; 213 final JavaScriptConstantCompiler _constants;
163 214
164 MirrorsDataImpl(this._compiler, this._options, this._commonElements, 215 MirrorsDataImpl(this._compiler, this._options, this._commonElements,
165 this._helpers, this._constants); 216 this._helpers, this._constants);
166 217
167 void registerUsedMember(MemberElement member) { 218 void registerUsedMember(MemberElement member) {
168 if (member == _helpers.disableTreeShakingMarker) { 219 if (member == _helpers.disableTreeShakingMarker) {
169 isTreeShakingDisabled = true; 220 isTreeShakingDisabled = true;
170 } else if (member == _helpers.preserveNamesMarker) { 221 } else if (member == _helpers.preserveNamesMarker) {
171 mustPreserveNames = true; 222 mustPreserveNames = true;
172 } else if (member == _helpers.preserveMetadataMarker) { 223 } else if (member == _helpers.preserveMetadataMarker) {
173 mustRetainMetadata = true; 224 mustRetainMetadata = true;
174 } else if (member == _helpers.preserveUrisMarker) { 225 } else if (member == _helpers.preserveUrisMarker) {
175 if (_options.preserveUris) mustPreserveUris = true; 226 if (_options.preserveUris) mustPreserveUris = true;
176 } else if (member == _helpers.preserveLibraryNamesMarker) { 227 } else if (member == _helpers.preserveLibraryNamesMarker) {
177 mustRetainLibraryNames = true; 228 mustRetainLibraryNames = true;
178 } 229 }
179 } 230 }
180 231
181 /// Should [element] (a getter) that would normally not be generated due to 232 bool shouldRetainGetter(FieldElement element) {
182 /// treeshaking be retained for reflection? 233 return isTreeShakingDisabled && isMemberAccessibleByReflection(element);
183 bool shouldRetainGetter(Element element) {
184 return isTreeShakingDisabled && isAccessibleByReflection(element);
185 } 234 }
186 235
187 /// Should [element] (a setter) hat would normally not be generated due to 236 bool shouldRetainSetter(FieldElement element) {
188 /// treeshaking be retained for reflection? 237 return isTreeShakingDisabled && isMemberAccessibleByReflection(element);
189 bool shouldRetainSetter(Element element) {
190 return isTreeShakingDisabled && isAccessibleByReflection(element);
191 } 238 }
192 239
193 /// Should [name] be retained for reflection? 240 /// Should [name] be retained for reflection?
194 bool shouldRetainName(String name) { 241 bool shouldRetainName(String name) {
195 if (hasInsufficientMirrorsUsed) return mustPreserveNames; 242 if (hasInsufficientMirrorsUsed) return mustPreserveNames;
196 if (name == '') return false; 243 if (name == '') return false;
197 return symbolsUsed.contains(name); 244 return symbolsUsed.contains(name);
198 } 245 }
199 246
200 bool retainMetadataOf(Element element) { 247 @override
201 if (mustRetainMetadata) hasRetainedMetadata = true; 248 bool retainMetadataOfParameter(ParameterElement element) {
202 if (mustRetainMetadata && referencedFromMirrorSystem(element)) { 249 if (mustRetainMetadata) {
203 for (MetadataAnnotation metadata in element.metadata) { 250 hasRetainedMetadata = true;
204 metadata.ensureResolved(_compiler.resolution); 251 if (isParameterReferencedFromMirrorSystem(element)) {
205 ConstantValue constant = 252 _retainMetadataOf(element);
206 _constants.getConstantValueForMetadata(metadata); 253 return true;
207 _constants.addCompileTimeConstantForEmission(constant);
208 } 254 }
209 return true;
210 } 255 }
211 return false; 256 return false;
212 } 257 }
213 258
259 @override
260 bool retainMetadataOfMember(MemberElement element) {
261 if (mustRetainMetadata) {
262 hasRetainedMetadata = true;
263 if (isMemberReferencedFromMirrorSystem(element)) {
264 _retainMetadataOf(element);
265 return true;
266 }
267 }
268 return false;
269 }
270
271 @override
272 bool retainMetadataOfClass(ClassElement element) {
273 if (mustRetainMetadata) {
274 hasRetainedMetadata = true;
275 if (isClassReferencedFromMirrorSystem(element)) {
276 _retainMetadataOf(element);
277 return true;
278 }
279 }
280 return false;
281 }
282
283 @override
284 bool retainMetadataOfTypedef(TypedefElement element) {
285 if (mustRetainMetadata) {
286 hasRetainedMetadata = true;
287 if (isTypedefReferencedFromMirrorSystem(element)) {
288 _retainMetadataOf(element);
289 return true;
290 }
291 }
292 return false;
293 }
294
295 @override
296 bool retainMetadataOfLibrary(LibraryElement element) {
297 if (mustRetainMetadata) {
298 hasRetainedMetadata = true;
299 if (isLibraryReferencedFromMirrorSystem(element)) {
300 _retainMetadataOf(element);
301 return true;
302 }
303 }
304 return false;
305 }
306
307 void _retainMetadataOf(Element element) {
308 for (MetadataAnnotation metadata in element.metadata) {
309 metadata.ensureResolved(_compiler.resolution);
310 ConstantValue constant = _constants.getConstantValueForMetadata(metadata);
311 _constants.addCompileTimeConstantForEmission(constant);
312 }
313 }
314
214 bool invokedReflectively(Element element) { 315 bool invokedReflectively(Element element) {
215 if (element.isParameter) { 316 if (element.isParameter) {
216 ParameterElement parameter = element; 317 ParameterElement parameter = element;
217 if (invokedReflectively(parameter.functionDeclaration)) return true; 318 if (invokedReflectively(parameter.functionDeclaration)) return true;
218 } 319 }
219 320
220 if (element.isField) { 321 if (element.isField) {
221 if (Elements.isStaticOrTopLevel(element) && 322 if (Elements.isStaticOrTopLevel(element) &&
222 (element.isFinal || element.isConst)) { 323 (element.isFinal || element.isConst)) {
223 return false; 324 return false;
224 } 325 }
225 } 326 }
226 327
227 return isAccessibleByReflection(element.declaration); 328 return isAccessibleByReflection(element.declaration);
228 } 329 }
229 330
230 /// Set of methods that are needed by reflection. Computed using 331 /// Sets of elements that are needed by reflection. Computed using
231 /// [computeMembersNeededForReflection] on first use. 332 /// [computeMembersNeededForReflection] on first use.
232 Set<Element> _membersNeededForReflection = null; 333 Set<ClassElement> _classesNeededForReflection;
233 Iterable<Element> get membersNeededForReflection { 334 Set<TypedefElement> _typedefsNeededForReflection;
234 assert(_membersNeededForReflection != null); 335 Set<MemberElement> _membersNeededForReflection;
235 return _membersNeededForReflection; 336 Set<LocalFunctionElement> _closuresNeededForReflection;
236 }
237 337
238 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed 338 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed
239 /// annotations. The arguments corresponds to the unions of the corresponding 339 /// annotations. The arguments corresponds to the unions of the corresponding
240 /// fields of the annotations. 340 /// fields of the annotations.
341 // TODO(johnniwinther): Change type of [metaTargets] to `Set<ClassEntity>`.
241 void registerMirrorUsage( 342 void registerMirrorUsage(
242 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) { 343 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) {
243 if (symbols == null && targets == null && metaTargets == null) { 344 if (symbols == null && targets == null && metaTargets == null) {
244 // The user didn't specify anything, or there are imports of 345 // The user didn't specify anything, or there are imports of
245 // 'dart:mirrors' without @MirrorsUsed. 346 // 'dart:mirrors' without @MirrorsUsed.
246 hasInsufficientMirrorsUsed = true; 347 hasInsufficientMirrorsUsed = true;
247 return; 348 return;
248 } 349 }
249 if (symbols != null) symbolsUsed.addAll(symbols); 350 if (symbols != null) symbolsUsed.addAll(symbols);
250 if (targets != null) { 351 if (targets != null) {
251 for (Element target in targets) { 352 for (Element target in targets) {
252 if (target.isAbstractField) { 353 if (target.isAbstractField) {
253 AbstractFieldElement field = target; 354 AbstractFieldElement field = target;
254 targetsUsed.add(field.getter); 355 if (field.getter != null) {
255 targetsUsed.add(field.setter); 356 membersInMirrorsUsedTargets.add(field.getter);
256 } else { 357 }
257 targetsUsed.add(target); 358 if (field.setter != null) {
359 membersInMirrorsUsedTargets.add(field.setter);
360 }
361 } else if (target.isClass) {
362 classesInMirrorsUsedTargets.add(target as ClassEntity);
363 } else if (target.isTypedef) {
364 _typedefsInMirrorsUsedTargets.add(target);
365 } else if (target.isLibrary) {
366 librariesInMirrorsUsedTargets.add(target as LibraryEntity);
367 } else if (target != null) {
368 membersInMirrorsUsedTargets.add(target as MemberEntity);
258 } 369 }
259 } 370 }
260 } 371 }
261 if (metaTargets != null) metaTargetsUsed.addAll(metaTargets); 372 if (metaTargets != null) {
373 for (var element in metaTargets) {
374 if (element is ClassEntity) {
375 metaTargetsUsed.add(element);
376 }
377 }
378 }
262 } 379 }
263 380
264 /// Returns `true` if [element] can be accessed through reflection, that is, 381 @override
265 /// is in the set of elements covered by a `MirrorsUsed` annotation. 382 bool isClassAccessibleByReflection(ClassElement element) {
266 /// 383 return _classesNeededForReflection.contains(_getDartClass(element));
267 /// This property is used to tag emitted elements with a marker which is 384 }
268 /// checked by the runtime system to throw an exception if an element is 385
269 /// accessed (invoked, get, set) that is not accessible for the reflective 386 @override
270 /// system. 387 bool isTypedefAccessibleByReflection(TypedefElement element) {
388 return _typedefsNeededForReflection.contains(element);
389 }
390
271 bool isAccessibleByReflection(Element element) { 391 bool isAccessibleByReflection(Element element) {
272 if (element.isClass) { 392 if (element.isLibrary) {
273 element = _getDartClass(element); 393 return false;
394 } else if (element.isClass) {
395 return isClassAccessibleByReflection(element);
396 } else if (element.isTypedef) {
397 return isTypedefAccessibleByReflection(element);
398 } else {
399 return isMemberAccessibleByReflection(element);
274 } 400 }
275 return membersNeededForReflection.contains(element);
276 } 401 }
277 402
278 ClassElement _getDartClass(ClassElement cls) { 403 ClassElement _getDartClass(ClassElement cls) {
279 if (cls == _helpers.jsIntClass) { 404 if (cls == _helpers.jsIntClass) {
280 return _commonElements.intClass; 405 return _commonElements.intClass;
281 } else if (cls == _helpers.jsBoolClass) { 406 } else if (cls == _helpers.jsBoolClass) {
282 return _commonElements.boolClass; 407 return _commonElements.boolClass;
283 } else if (cls == _helpers.jsNumberClass) { 408 } else if (cls == _helpers.jsNumberClass) {
284 return _commonElements.numClass; 409 return _commonElements.numClass;
285 } else if (cls == _helpers.jsDoubleClass) { 410 } else if (cls == _helpers.jsDoubleClass) {
286 return _commonElements.doubleClass; 411 return _commonElements.doubleClass;
287 } else if (cls == _helpers.jsStringClass) { 412 } else if (cls == _helpers.jsStringClass) {
288 return _commonElements.stringClass; 413 return _commonElements.stringClass;
289 } else if (cls == _helpers.jsArrayClass) { 414 } else if (cls == _helpers.jsArrayClass) {
290 return _commonElements.listClass; 415 return _commonElements.listClass;
291 } else if (cls == _helpers.jsNullClass) { 416 } else if (cls == _helpers.jsNullClass) {
292 return _commonElements.nullClass; 417 return _commonElements.nullClass;
293 } else { 418 } else {
294 return cls; 419 return cls;
295 } 420 }
296 } 421 }
297 422
298 /// Returns `true` if this member element needs reflection information at
299 /// runtime.
300 bool isMemberAccessibleByReflection(MemberElement element) { 423 bool isMemberAccessibleByReflection(MemberElement element) {
301 return membersNeededForReflection.contains(element); 424 return _membersNeededForReflection.contains(element);
302 } 425 }
303 426
304 /// Returns true if this element has to be enqueued due to 427 /// Returns true if this element has to be enqueued due to
305 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if 428 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if
306 /// normal tree shaking is still active ([isTreeShakingDisabled] is false). 429 /// normal tree shaking is still active ([isTreeShakingDisabled] is false).
307 bool requiredByMirrorSystem(Element element) { 430 bool requiredByMirrorSystem(Element element) {
308 return hasInsufficientMirrorsUsed && isTreeShakingDisabled || 431 return hasInsufficientMirrorsUsed && isTreeShakingDisabled ||
309 matchesMirrorsMetaTarget(element) || 432 matchesMirrorsMetaTarget(element) ||
310 targetsUsed.contains(element); 433 classesInMirrorsUsedTargets.contains(element) ||
434 membersInMirrorsUsedTargets.contains(element) ||
435 librariesInMirrorsUsedTargets.contains(element) ||
436 _typedefsInMirrorsUsedTargets.contains(element);
311 } 437 }
312 438
313 /// Returns true if this element is covered by a mirrorsUsed annotation. 439 @override
314 /// 440 bool isLibraryReferencedFromMirrorSystem(LibraryElement element) {
315 /// Note that it might still be ok to tree shake the element away if no 441 return _libraryReferencedFromMirrorSystem(element);
316 /// reflection is used in the program (and thus [isTreeShakingDisabled] is 442 }
317 /// still false). Therefore _do not_ use this predicate to decide inclusion
318 /// in the tree, use [requiredByMirrorSystem] instead.
319 bool referencedFromMirrorSystem(Element element, [recursive = true]) {
320 Element enclosing = recursive ? element.enclosingElement : null;
321 443
444 @override
445 bool isMemberReferencedFromMirrorSystem(MemberElement element) {
446 if (_memberReferencedFromMirrorSystem(element)) return true;
447 if (element.enclosingClass != null) {
448 return isClassReferencedFromMirrorSystem(element.enclosingClass);
449 } else {
450 return isLibraryReferencedFromMirrorSystem(element.library);
451 }
452 }
453
454 @override
455 bool isClassReferencedFromMirrorSystem(ClassElement element) {
456 return _classReferencedFromMirrorSystem(element) ||
457 isLibraryReferencedFromMirrorSystem(element.library);
458 }
459
460 bool isParameterReferencedFromMirrorSystem(ParameterElement element) {
461 return _parameterReferencedFromMirrorSystem(element) ||
462 isMemberReferencedFromMirrorSystem(element.memberContext);
463 }
464
465 bool isTypedefReferencedFromMirrorSystem(TypedefElement element) {
466 return _typedefReferencedFromMirrorSystem(element) ||
467 isLibraryReferencedFromMirrorSystem(element.library);
468 }
469
470 bool _memberReferencedFromMirrorSystem(MemberElement element) {
322 return hasInsufficientMirrorsUsed || 471 return hasInsufficientMirrorsUsed ||
323 matchesMirrorsMetaTarget(element) || 472 matchesMirrorsMetaTarget(element) ||
324 targetsUsed.contains(element) || 473 membersInMirrorsUsedTargets.contains(element);
325 (enclosing != null && referencedFromMirrorSystem(enclosing)); 474 }
475
476 bool _parameterReferencedFromMirrorSystem(ParameterElement element) {
477 return hasInsufficientMirrorsUsed || matchesMirrorsMetaTarget(element);
478 }
479
480 bool _classReferencedFromMirrorSystem(ClassElement element) {
481 return hasInsufficientMirrorsUsed ||
482 matchesMirrorsMetaTarget(element) ||
483 classesInMirrorsUsedTargets.contains(element);
484 }
485
486 bool _typedefReferencedFromMirrorSystem(TypedefElement element) {
487 return hasInsufficientMirrorsUsed ||
488 matchesMirrorsMetaTarget(element) ||
489 _typedefsInMirrorsUsedTargets.contains(element);
490 }
491
492 bool _libraryReferencedFromMirrorSystem(LibraryElement element) {
493 return hasInsufficientMirrorsUsed ||
494 matchesMirrorsMetaTarget(element) ||
495 librariesInMirrorsUsedTargets.contains(element);
326 } 496 }
327 497
328 /** 498 /**
329 * Returns `true` if the element is needed because it has an annotation 499 * Returns `true` if the element is needed because it has an annotation
330 * of a type that is used as a meta target for reflection. 500 * of a type that is used as a meta target for reflection.
331 */ 501 */
332 bool matchesMirrorsMetaTarget(Element element) { 502 bool matchesMirrorsMetaTarget(Element element) {
333 if (metaTargetsUsed.isEmpty) return false; 503 if (metaTargetsUsed.isEmpty) return false;
334 for (MetadataAnnotation metadata in element.metadata) { 504 for (MetadataAnnotation metadata in element.metadata) {
335 // TODO(kasperl): It would be nice if we didn't have to resolve 505 // TODO(kasperl): It would be nice if we didn't have to resolve
336 // all metadata but only stuff that potentially would match one 506 // all metadata but only stuff that potentially would match one
337 // of the used meta targets. 507 // of the used meta targets.
338 metadata.ensureResolved(_compiler.resolution); 508 metadata.ensureResolved(_compiler.resolution);
339 ConstantValue value = 509 ConstantValue value =
340 _compiler.constants.getConstantValue(metadata.constant); 510 _compiler.constants.getConstantValue(metadata.constant);
341 if (value == null) continue; 511 if (value == null) continue;
342 ResolutionDartType type = value.getType(_commonElements); 512 DartType type = value.getType(_commonElements);
343 if (metaTargetsUsed.contains(type.element)) return true; 513 if (type is InterfaceType && metaTargetsUsed.contains(type.element))
514 return true;
344 } 515 }
345 return false; 516 return false;
346 } 517 }
347 518
348 /** 519 /**
349 * Visits all classes and computes whether its members are needed for 520 * Visits all classes and computes whether its members are needed for
350 * reflection. 521 * reflection.
351 * 522 *
352 * We have to precompute this set as we cannot easily answer the need for 523 * We have to precompute this set as we cannot easily answer the need for
353 * reflection locally when looking at the member: We lack the information by 524 * reflection locally when looking at the member: We lack the information by
354 * which classes a member is inherited. Called after resolution is complete. 525 * which classes a member is inherited. Called after resolution is complete.
355 * 526 *
356 * We filter out private libraries here, as their elements should not 527 * We filter out private libraries here, as their elements should not
357 * be visible by reflection unless some other interfaces makes them 528 * be visible by reflection unless some other interfaces makes them
358 * accessible. 529 * accessible.
359 */ 530 */
360 void computeMembersNeededForReflection( 531 void computeMembersNeededForReflection(
361 ResolutionWorldBuilder worldBuilder, ClosedWorld closedWorld) { 532 ResolutionWorldBuilder worldBuilder, ClosedWorld closedWorld) {
362 if (_membersNeededForReflection != null) return; 533 if (_membersNeededForReflection != null) return;
363 if (closedWorld.commonElements.mirrorsLibrary == null) { 534 if (closedWorld.commonElements.mirrorsLibrary == null) {
364 _membersNeededForReflection = const ImmutableEmptySet<Element>(); 535 _classesNeededForReflection = const ImmutableEmptySet<ClassElement>();
536 _typedefsNeededForReflection = const ImmutableEmptySet<TypedefElement>();
537 _membersNeededForReflection = const ImmutableEmptySet<MemberElement>();
538 _closuresNeededForReflection =
539 const ImmutableEmptySet<LocalFunctionElement>();
365 return; 540 return;
366 } 541 }
542 _classesNeededForReflection = new Set<ClassElement>();
543 _typedefsNeededForReflection = new Set<TypedefElement>();
544 _membersNeededForReflection = new Set<MemberElement>();
545 _closuresNeededForReflection = new Set<LocalFunctionElement>();
546
367 // Compute a mapping from class to the closures it contains, so we 547 // Compute a mapping from class to the closures it contains, so we
368 // can include the correct ones when including the class. 548 // can include the correct ones when including the class.
369 Map<ClassElement, List<LocalFunctionElement>> closureMap = 549 Map<ClassElement, List<LocalFunctionElement>> closureMap =
370 new Map<ClassElement, List<LocalFunctionElement>>(); 550 new Map<ClassElement, List<LocalFunctionElement>>();
371 for (LocalFunctionElement closure in worldBuilder.localFunctions) { 551 for (LocalFunctionElement closure in worldBuilder.localFunctions) {
372 closureMap.putIfAbsent(closure.enclosingClass, () => []).add(closure); 552 closureMap.putIfAbsent(closure.enclosingClass, () => []).add(closure);
373 } 553 }
374 bool foundClosure = false; 554 bool foundClosure = false;
375 Set<Element> reflectableMembers = new Set<Element>();
376 for (ClassElement cls in worldBuilder.directlyInstantiatedClasses) { 555 for (ClassElement cls in worldBuilder.directlyInstantiatedClasses) {
377 // Do not process internal classes. 556 // Do not process internal classes.
378 if (cls.library.isInternalLibrary || cls.isInjected) continue; 557 if (cls.library.isInternalLibrary || cls.isInjected) continue;
379 if (referencedFromMirrorSystem(cls)) { 558 if (isClassReferencedFromMirrorSystem(cls)) {
380 Set<Name> memberNames = new Set<Name>(); 559 Set<Name> memberNames = new Set<Name>();
381 // 1) the class (should be resolved) 560 // 1) the class (should be resolved)
382 assert(invariant(cls, cls.isResolved)); 561 assert(invariant(cls, cls.isResolved));
383 reflectableMembers.add(cls); 562 _classesNeededForReflection.add(cls);
384 // 2) its constructors (if resolved) 563 // 2) its constructors (if resolved)
385 cls.constructors.forEach((ConstructorElement constructor) { 564 cls.constructors.forEach((ConstructorElement constructor) {
386 if (worldBuilder.isMemberUsed(constructor)) { 565 if (worldBuilder.isMemberUsed(constructor)) {
387 reflectableMembers.add(constructor); 566 _membersNeededForReflection.add(constructor);
388 } 567 }
389 }); 568 });
390 // 3) all members, including fields via getter/setters (if resolved) 569 // 3) all members, including fields via getter/setters (if resolved)
391 cls.forEachClassMember((Member member) { 570 cls.forEachClassMember((Member member) {
392 MemberElement element = member.element; 571 MemberElement element = member.element;
393 if (worldBuilder.isMemberUsed(element)) { 572 if (worldBuilder.isMemberUsed(element)) {
394 memberNames.add(member.name); 573 memberNames.add(member.name);
395 reflectableMembers.add(element); 574 _membersNeededForReflection.add(element);
396 element.nestedClosures 575 element.nestedClosures
397 .forEach((SynthesizedCallMethodElementX callFunction) { 576 .forEach((SynthesizedCallMethodElementX callFunction) {
398 reflectableMembers.add(callFunction); 577 _membersNeededForReflection.add(callFunction);
399 reflectableMembers.add(callFunction.closureClass); 578 _classesNeededForReflection.add(callFunction.closureClass);
400 }); 579 });
401 } 580 }
402 }); 581 });
403 // 4) all overriding members of subclasses/subtypes (should be resolved) 582 // 4) all overriding members of subclasses/subtypes (should be resolved)
404 if (closedWorld.hasAnyStrictSubtype(cls)) { 583 if (closedWorld.hasAnyStrictSubtype(cls)) {
405 closedWorld.forEachStrictSubtypeOf(cls, (ClassElement subcls) { 584 closedWorld.forEachStrictSubtypeOf(cls, (ClassElement subcls) {
406 subcls.forEachClassMember((Member member) { 585 subcls.forEachClassMember((Member member) {
407 if (memberNames.contains(member.name)) { 586 if (memberNames.contains(member.name)) {
408 // TODO(20993): find out why this assertion fails. 587 // TODO(20993): find out why this assertion fails.
409 // assert(invariant(member.element, 588 // assert(invariant(member.element,
410 // worldBuilder.isMemberUsed(member.element))); 589 // worldBuilder.isMemberUsed(member.element)));
411 if (worldBuilder.isMemberUsed(member.element)) { 590 if (worldBuilder.isMemberUsed(member.element)) {
412 reflectableMembers.add(member.element); 591 _membersNeededForReflection.add(member.element);
413 } 592 }
414 } 593 }
415 }); 594 });
416 }); 595 });
417 } 596 }
418 // 5) all its closures 597 // 5) all its closures
419 List<LocalFunctionElement> closures = closureMap[cls]; 598 List<LocalFunctionElement> closures = closureMap[cls];
420 if (closures != null) { 599 if (closures != null) {
421 reflectableMembers.addAll(closures); 600 _closuresNeededForReflection.addAll(closures);
422 foundClosure = true; 601 foundClosure = true;
423 } 602 }
424 } else { 603 } else {
425 // check members themselves 604 // check members themselves
426 cls.constructors.forEach((ConstructorElement element) { 605 cls.constructors.forEach((ConstructorElement element) {
427 if (!worldBuilder.isMemberUsed(element)) return; 606 if (!worldBuilder.isMemberUsed(element)) return;
428 if (referencedFromMirrorSystem(element, false)) { 607 if (_memberReferencedFromMirrorSystem(element)) {
429 reflectableMembers.add(element); 608 _membersNeededForReflection.add(element);
430 } 609 }
431 }); 610 });
432 cls.forEachClassMember((Member member) { 611 cls.forEachClassMember((Member member) {
433 if (!worldBuilder.isMemberUsed(member.element)) return; 612 if (!worldBuilder.isMemberUsed(member.element)) return;
434 if (referencedFromMirrorSystem(member.element, false)) { 613 if (_memberReferencedFromMirrorSystem(member.element)) {
435 reflectableMembers.add(member.element); 614 _membersNeededForReflection.add(member.element);
436 } 615 }
437 }); 616 });
438 // Also add in closures. Those might be reflectable is their enclosing 617 // Also add in closures. Those might be reflectable is their enclosing
439 // member is. 618 // member is.
440 List<LocalFunctionElement> closures = closureMap[cls]; 619 List<LocalFunctionElement> closures = closureMap[cls];
441 if (closures != null) { 620 if (closures != null) {
442 for (LocalFunctionElement closure in closures) { 621 for (LocalFunctionElement closure in closures) {
443 MemberElement member = closure.memberContext; 622 MemberElement member = closure.memberContext;
444 if (referencedFromMirrorSystem(member, false)) { 623 if (_memberReferencedFromMirrorSystem(member)) {
445 reflectableMembers.add(closure); 624 _closuresNeededForReflection.add(closure);
446 foundClosure = true; 625 foundClosure = true;
447 } 626 }
448 } 627 }
449 } 628 }
450 } 629 }
451 } 630 }
452 // We also need top-level non-class elements like static functions and 631 // We also need top-level non-class elements like static functions and
453 // global fields. We use the resolution queue to decide which elements are 632 // global fields. We use the resolution queue to decide which elements are
454 // part of the live world. 633 // part of the live world.
455 for (LibraryElement lib in _compiler.libraryLoader.libraries) { 634 for (LibraryElement lib in _compiler.libraryLoader.libraries) {
456 if (lib.isInternalLibrary) continue; 635 if (lib.isInternalLibrary) continue;
457 lib.forEachLocalMember((Element element) { 636 lib.forEachLocalMember((Element element) {
458 if (element.isClass || element.isTypedef) return; 637 if (element.isClass || element.isTypedef) return;
459 MemberElement member = element; 638 MemberElement member = element;
460 if (worldBuilder.isMemberUsed(member) && 639 if (worldBuilder.isMemberUsed(member) &&
461 referencedFromMirrorSystem(member)) { 640 isMemberReferencedFromMirrorSystem(member)) {
462 reflectableMembers.add(member); 641 _membersNeededForReflection.add(member);
463 } 642 }
464 }); 643 });
465 } 644 }
466 // And closures inside top-level elements that do not have a surrounding 645 // And closures inside top-level elements that do not have a surrounding
467 // class. These will be in the [:null:] bucket of the [closureMap]. 646 // class. These will be in the [:null:] bucket of the [closureMap].
468 if (closureMap.containsKey(null)) { 647 if (closureMap.containsKey(null)) {
469 for (Element closure in closureMap[null]) { 648 for (LocalFunctionElement closure in closureMap[null]) {
470 if (referencedFromMirrorSystem(closure)) { 649 if (isMemberReferencedFromMirrorSystem(closure.memberContext)) {
471 reflectableMembers.add(closure); 650 _closuresNeededForReflection.add(closure);
472 foundClosure = true; 651 foundClosure = true;
473 } 652 }
474 } 653 }
475 } 654 }
476 // As we do not think about closures as classes, yet, we have to make sure 655 // As we do not think about closures as classes, yet, we have to make sure
477 // their superclasses are available for reflection manually. 656 // their superclasses are available for reflection manually.
478 if (foundClosure) { 657 if (foundClosure) {
479 ClassElement cls = _helpers.closureClass; 658 ClassElement cls = _helpers.closureClass;
480 reflectableMembers.add(cls); 659 _classesNeededForReflection.add(cls);
481 } 660 }
482 Set<MethodElement> closurizedMembers = worldBuilder.closurizedMembers; 661 Set<MethodElement> closurizedMembers = worldBuilder.closurizedMembers;
483 if (closurizedMembers.any(reflectableMembers.contains)) { 662 if (closurizedMembers.any(_membersNeededForReflection.contains)) {
484 ClassElement cls = _helpers.boundClosureClass; 663 ClassElement cls = _helpers.boundClosureClass;
485 reflectableMembers.add(cls); 664 _classesNeededForReflection.add(cls);
486 } 665 }
487 // Add typedefs. 666 // Add typedefs.
488 reflectableMembers 667 _typedefsNeededForReflection.addAll(
489 .addAll(closedWorld.allTypedefs.where(referencedFromMirrorSystem)); 668 closedWorld.allTypedefs.where(isTypedefReferencedFromMirrorSystem));
490 // Register all symbols of reflectable elements 669 // Register all symbols of reflectable elements
491 for (Element element in reflectableMembers) { 670 for (ClassElement element in _classesNeededForReflection) {
492 symbolsUsed.add(element.name); 671 symbolsUsed.add(element.name);
493 } 672 }
494 _membersNeededForReflection = reflectableMembers; 673 for (TypedefElement element in _typedefsNeededForReflection) {
674 symbolsUsed.add(element.name);
675 }
676 for (MemberElement element in _membersNeededForReflection) {
677 symbolsUsed.add(element.name);
678 }
679 for (LocalFunctionElement element in _closuresNeededForReflection) {
680 symbolsUsed.add(element.name);
681 }
495 } 682 }
496 683
497 // TODO(20791): compute closure classes after resolution and move this code to 684 // TODO(20791): compute closure classes after resolution and move this code to
498 // [computeMembersNeededForReflection]. 685 // [computeMembersNeededForReflection].
499 void maybeMarkClosureAsNeededForReflection( 686 void maybeMarkClosureAsNeededForReflection(
500 ClosureClassElement globalizedElement, 687 ClosureClassElement globalizedElement,
501 FunctionElement callFunction, 688 MethodElement callFunction,
502 FunctionElement function) { 689 LocalFunctionElement function) {
503 if (!_membersNeededForReflection.contains(function)) return; 690 if (!_closuresNeededForReflection.contains(function)) return;
504 _membersNeededForReflection.add(callFunction); 691 _membersNeededForReflection.add(callFunction);
505 _membersNeededForReflection.add(globalizedElement); 692 _classesNeededForReflection.add(globalizedElement);
506 } 693 }
507 694
508 /// Called when `const Symbol(name)` is seen. 695 /// Called when `const Symbol(name)` is seen.
509 void registerConstSymbol(String name) { 696 void registerConstSymbol(String name) {
510 symbolsUsed.add(name); 697 symbolsUsed.add(name);
511 if (name.endsWith('=')) { 698 if (name.endsWith('=')) {
512 symbolsUsed.add(name.substring(0, name.length - 1)); 699 symbolsUsed.add(name.substring(0, name.length - 1));
513 } 700 }
514 } 701 }
515 } 702 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/mirrors_analysis.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