OLD | NEW |
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/entities.dart'; | 11 import '../elements/entities.dart'; |
12 import '../elements/names.dart'; | 12 import '../elements/names.dart'; |
13 import '../elements/types.dart'; | 13 import '../elements/types.dart'; |
14 import '../options.dart'; | 14 import '../options.dart'; |
15 import '../world.dart'; | 15 import '../world.dart'; |
16 import '../universe/world_builder.dart'; | 16 import '../universe/world_builder.dart'; |
17 import '../util/emptyset.dart'; | 17 import '../util/emptyset.dart'; |
18 import 'constant_handler_javascript.dart'; | |
19 | 18 |
20 abstract class MirrorsData { | 19 abstract class MirrorsData { |
21 /// True if a call to preserveMetadataMarker has been seen. This means that | 20 /// True if a call to preserveMetadataMarker has been seen. This means that |
22 /// metadata must be retained for dart:mirrors to work correctly. | 21 /// metadata must be retained for dart:mirrors to work correctly. |
23 // resolution-empty-queue | 22 // resolution-empty-queue |
24 bool get mustRetainMetadata; | 23 bool get mustRetainMetadata; |
25 | 24 |
26 /// True if any metadata has been retained. This is slightly different from | 25 /// True if any metadata has been retained. This is slightly different from |
27 /// [mustRetainMetadata] and tells us if any metadata was retained. For | 26 /// [mustRetainMetadata] and tells us if any metadata was retained. For |
28 /// example, if [mustRetainMetadata] is true but there is no metadata in the | 27 /// example, if [mustRetainMetadata] is true but there is no metadata in the |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 /// Should [name] be retained for reflection? | 70 /// Should [name] be retained for reflection? |
72 bool shouldRetainName(String name); | 71 bool shouldRetainName(String name); |
73 | 72 |
74 /// Returns `true` if the class [element] is covered by a `MirrorsUsed` | 73 /// Returns `true` if the class [element] is covered by a `MirrorsUsed` |
75 /// annotation. | 74 /// annotation. |
76 /// | 75 /// |
77 /// Note that it might still be ok to tree shake the element away if no | 76 /// Note that it might still be ok to tree shake the element away if no |
78 /// reflection is used in the program (and thus [isTreeShakingDisabled] is | 77 /// reflection is used in the program (and thus [isTreeShakingDisabled] is |
79 /// still false). Therefore _do not_ use this predicate to decide inclusion | 78 /// still false). Therefore _do not_ use this predicate to decide inclusion |
80 /// in the tree, use [requiredByMirrorSystem] instead. | 79 /// in the tree, use [requiredByMirrorSystem] instead. |
81 bool isClassReferencedFromMirrorSystem(covariant ClassEntity element); | 80 bool isClassReferencedFromMirrorSystem(ClassEntity element); |
82 | 81 |
83 /// Returns `true` if the member [element] is covered by a `MirrorsUsed` | 82 /// Returns `true` if the member [element] is covered by a `MirrorsUsed` |
84 /// annotation. | 83 /// annotation. |
85 /// | 84 /// |
86 /// Note that it might still be ok to tree shake the element away if no | 85 /// 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 | 86 /// reflection is used in the program (and thus [isTreeShakingDisabled] is |
88 /// still false). Therefore _do not_ use this predicate to decide inclusion | 87 /// still false). Therefore _do not_ use this predicate to decide inclusion |
89 /// in the tree, use [requiredByMirrorSystem] instead. | 88 /// in the tree, use [requiredByMirrorSystem] instead. |
90 bool isMemberReferencedFromMirrorSystem(covariant MemberEntity element); | 89 bool isMemberReferencedFromMirrorSystem(MemberEntity element); |
91 | 90 |
92 /// Returns `true` if the library [element] is covered by a `MirrorsUsed` | 91 /// Returns `true` if the library [element] is covered by a `MirrorsUsed` |
93 /// annotation. | 92 /// annotation. |
94 bool isLibraryReferencedFromMirrorSystem(covariant LibraryEntity element); | 93 bool isLibraryReferencedFromMirrorSystem(LibraryEntity element); |
95 | 94 |
96 /// Returns `true` if the typedef [element] needs reflection information at | 95 /// Returns `true` if the typedef [element] needs reflection information at |
97 /// runtime. | 96 /// runtime. |
98 /// | 97 /// |
99 /// This property is used to tag emitted elements with a marker which is | 98 /// This property is used to tag emitted elements with a marker which is |
100 /// checked by the runtime system to throw an exception if an element is | 99 /// checked by the runtime system to throw an exception if an element is |
101 /// accessed (invoked, get, set) that is not accessible for the reflective | 100 /// accessed (invoked, get, set) that is not accessible for the reflective |
102 /// system. | 101 /// system. |
103 bool isTypedefAccessibleByReflection(covariant TypedefEntity element); | 102 bool isTypedefAccessibleByReflection(TypedefEntity element); |
104 | 103 |
105 /// Returns `true` if the class [element] needs reflection information at | 104 /// Returns `true` if the class [element] needs reflection information at |
106 /// runtime. | 105 /// runtime. |
107 /// | 106 /// |
108 /// This property is used to tag emitted elements with a marker which is | 107 /// 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 | 108 /// 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 | 109 /// accessed (invoked, get, set) that is not accessible for the reflective |
111 /// system. | 110 /// system. |
112 bool isClassAccessibleByReflection(ClassEntity element); | 111 bool isClassAccessibleByReflection(ClassEntity element); |
113 | 112 |
114 /// Returns `true` if the member [element] needs reflection information at | 113 /// Returns `true` if the member [element] needs reflection information at |
115 /// runtime. | 114 /// runtime. |
116 /// | 115 /// |
117 /// This property is used to tag emitted elements with a marker which is | 116 /// 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 | 117 /// 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 | 118 /// accessed (invoked, get, set) that is not accessible for the reflective |
120 /// system. | 119 /// system. |
121 bool isMemberAccessibleByReflection(MemberEntity element); | 120 bool isMemberAccessibleByReflection(MemberEntity element); |
122 | 121 |
123 // TODO(johnniwinther): Remove this. | 122 bool retainMetadataOfLibrary(LibraryEntity element, |
124 @deprecated | |
125 bool isAccessibleByReflection(Element element); | |
126 | |
127 bool retainMetadataOfLibrary(covariant LibraryEntity element, | |
128 {bool addForEmission: true}); | 123 {bool addForEmission: true}); |
129 bool retainMetadataOfTypedef(covariant TypedefEntity element); | 124 bool retainMetadataOfTypedef(TypedefEntity element); |
130 bool retainMetadataOfClass(covariant ClassEntity element); | 125 bool retainMetadataOfClass(ClassEntity element); |
131 bool retainMetadataOfMember(covariant MemberEntity element); | 126 bool retainMetadataOfMember(MemberEntity element); |
132 bool retainMetadataOfParameter(ParameterElement element); | |
133 | 127 |
134 /// Returns true if this element has to be enqueued due to | 128 /// Returns true if this element has to be enqueued due to |
135 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if | 129 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if |
136 /// normal tree shaking is still active ([isTreeShakingDisabled] is false). | 130 /// normal tree shaking is still active ([isTreeShakingDisabled] is false). |
137 bool requiredByMirrorSystem(Element element); | 131 bool isLibraryRequiredByMirrorSystem(LibraryEntity element); |
| 132 bool isClassRequiredByMirrorSystem(ClassEntity element); |
| 133 bool isMemberRequiredByMirrorSystem(MemberEntity element); |
138 } | 134 } |
139 | 135 |
140 abstract class MirrorsDataBuilder { | 136 abstract class MirrorsDataBuilder { |
141 void registerUsedMember(MemberElement member); | 137 void registerUsedMember(MemberEntity member); |
142 | 138 |
143 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed | 139 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed |
144 /// annotations. The arguments corresponds to the unions of the corresponding | 140 /// annotations. The arguments corresponds to the unions of the corresponding |
145 /// fields of the annotations. | 141 /// fields of the annotations. |
146 void registerMirrorUsage( | 142 void registerMirrorUsage( |
147 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets); | 143 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets); |
148 | 144 |
149 /// Called when `const Symbol(name)` is seen. | 145 /// Called when `const Symbol(name)` is seen. |
150 void registerConstSymbol(String name); | 146 void registerConstSymbol(String name); |
151 | 147 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 | 194 |
199 /// List of annotations provided by user that indicate that the annotated | 195 /// List of annotations provided by user that indicate that the annotated |
200 /// element must be retained. | 196 /// element must be retained. |
201 final Set<ClassEntity> metaTargetsUsed = new Set<ClassEntity>(); | 197 final Set<ClassEntity> metaTargetsUsed = new Set<ClassEntity>(); |
202 | 198 |
203 // TODO(johnniwinther): Avoid the need for this. | 199 // TODO(johnniwinther): Avoid the need for this. |
204 final Compiler _compiler; | 200 final Compiler _compiler; |
205 | 201 |
206 final CompilerOptions _options; | 202 final CompilerOptions _options; |
207 | 203 |
| 204 final ElementEnvironment _elementEnvironment; |
208 final CommonElements _commonElements; | 205 final CommonElements _commonElements; |
209 | 206 |
210 MirrorsDataImpl(this._compiler, this._options, this._commonElements); | 207 MirrorsDataImpl(this._compiler, this._options, this._elementEnvironment, |
| 208 this._commonElements); |
211 | 209 |
212 JavaScriptConstantCompiler get _constants => _compiler.backend.constants; | 210 void registerUsedMember(MemberEntity member) { |
213 | |
214 void registerUsedMember(MemberElement member) { | |
215 if (member == _commonElements.disableTreeShakingMarker) { | 211 if (member == _commonElements.disableTreeShakingMarker) { |
216 isTreeShakingDisabled = true; | 212 isTreeShakingDisabled = true; |
217 } else if (member == _commonElements.preserveNamesMarker) { | 213 } else if (member == _commonElements.preserveNamesMarker) { |
218 mustPreserveNames = true; | 214 mustPreserveNames = true; |
219 } else if (member == _commonElements.preserveMetadataMarker) { | 215 } else if (member == _commonElements.preserveMetadataMarker) { |
220 mustRetainMetadata = true; | 216 mustRetainMetadata = true; |
221 } else if (member == _commonElements.preserveUrisMarker) { | 217 } else if (member == _commonElements.preserveUrisMarker) { |
222 if (_options.preserveUris) mustPreserveUris = true; | 218 if (_options.preserveUris) mustPreserveUris = true; |
223 } else if (member == _commonElements.preserveLibraryNamesMarker) { | 219 } else if (member == _commonElements.preserveLibraryNamesMarker) { |
224 mustRetainLibraryNames = true; | 220 mustRetainLibraryNames = true; |
225 } | 221 } |
226 } | 222 } |
227 | 223 |
228 bool shouldRetainGetter(FieldEntity element) { | 224 bool shouldRetainGetter(FieldEntity element) { |
229 return isTreeShakingDisabled && isMemberAccessibleByReflection(element); | 225 return isTreeShakingDisabled && isMemberAccessibleByReflection(element); |
230 } | 226 } |
231 | 227 |
232 bool shouldRetainSetter(FieldEntity element) { | 228 bool shouldRetainSetter(FieldEntity element) { |
233 return isTreeShakingDisabled && isMemberAccessibleByReflection(element); | 229 return isTreeShakingDisabled && isMemberAccessibleByReflection(element); |
234 } | 230 } |
235 | 231 |
236 /// Should [name] be retained for reflection? | 232 /// Should [name] be retained for reflection? |
237 bool shouldRetainName(String name) { | 233 bool shouldRetainName(String name) { |
238 if (hasInsufficientMirrorsUsed) return mustPreserveNames; | 234 if (hasInsufficientMirrorsUsed) return mustPreserveNames; |
239 if (name == '') return false; | 235 if (name == '') return false; |
240 return symbolsUsed.contains(name); | 236 return symbolsUsed.contains(name); |
241 } | 237 } |
242 | 238 |
243 @override | 239 @override |
244 bool retainMetadataOfParameter(ParameterElement element) { | 240 bool retainMetadataOfMember(covariant MemberElement element) { |
245 if (mustRetainMetadata) { | 241 if (mustRetainMetadata) { |
246 hasRetainedMetadata = true; | 242 hasRetainedMetadata = true; |
247 if (isParameterReferencedFromMirrorSystem(element)) { | 243 if (isMemberReferencedFromMirrorSystem(element)) { |
248 _retainMetadataOf(element); | 244 _addConstantsForEmission( |
| 245 getMemberMetadata(element, includeParameterMetadata: true)); |
249 return true; | 246 return true; |
250 } | 247 } |
251 } | 248 } |
252 return false; | |
253 } | |
254 | |
255 @override | |
256 bool retainMetadataOfMember(MemberElement element) { | |
257 if (mustRetainMetadata) { | |
258 hasRetainedMetadata = true; | |
259 if (isMemberReferencedFromMirrorSystem(element)) { | |
260 _retainMetadataOf(element); | |
261 return true; | |
262 } | |
263 } | |
264 return false; | 249 return false; |
265 } | 250 } |
266 | 251 |
267 @override | 252 @override |
268 bool retainMetadataOfClass(ClassElement element) { | 253 bool retainMetadataOfClass(ClassEntity element) { |
269 if (mustRetainMetadata) { | 254 if (mustRetainMetadata) { |
270 hasRetainedMetadata = true; | 255 hasRetainedMetadata = true; |
271 if (isClassReferencedFromMirrorSystem(element)) { | 256 if (isClassReferencedFromMirrorSystem(element)) { |
272 _retainMetadataOf(element); | 257 _addConstantsForEmission(getClassMetadata(element)); |
273 return true; | 258 return true; |
274 } | 259 } |
275 } | 260 } |
276 return false; | 261 return false; |
277 } | 262 } |
278 | 263 |
279 @override | 264 @override |
280 bool retainMetadataOfTypedef(TypedefElement element) { | 265 bool retainMetadataOfTypedef(TypedefEntity element) { |
281 if (mustRetainMetadata) { | 266 if (mustRetainMetadata) { |
282 hasRetainedMetadata = true; | 267 hasRetainedMetadata = true; |
283 if (isTypedefReferencedFromMirrorSystem(element)) { | 268 if (_isTypedefReferencedFromMirrorSystem(element)) { |
284 _retainMetadataOf(element); | 269 _addConstantsForEmission(getTypedefMetadata(element)); |
285 return true; | 270 return true; |
286 } | 271 } |
287 } | 272 } |
288 return false; | 273 return false; |
289 } | 274 } |
290 | 275 |
291 @override | 276 @override |
292 bool retainMetadataOfLibrary(LibraryElement element, | 277 bool retainMetadataOfLibrary(LibraryEntity element, |
293 {bool addForEmission: true}) { | 278 {bool addForEmission: true}) { |
294 if (mustRetainMetadata) { | 279 if (mustRetainMetadata) { |
295 hasRetainedMetadata = true; | 280 hasRetainedMetadata = true; |
296 if (isLibraryReferencedFromMirrorSystem(element)) { | 281 if (isLibraryReferencedFromMirrorSystem(element)) { |
297 _retainMetadataOf(element, addForEmission: addForEmission); | 282 Iterable<ConstantValue> constants = getLibraryMetadata(element); |
| 283 if (addForEmission) { |
| 284 _addConstantsForEmission(constants); |
| 285 } |
298 return true; | 286 return true; |
299 } | 287 } |
300 } | 288 } |
301 return false; | 289 return false; |
302 } | 290 } |
303 | 291 |
304 void _retainMetadataOf(Element element, {bool addForEmission: true}) { | 292 Iterable<ConstantValue> getLibraryMetadata(LibraryElement element) { |
305 for (MetadataAnnotation metadata in element.metadata) { | 293 return _elementEnvironment.getLibraryMetadata(element); |
306 metadata.ensureResolved(_compiler.resolution); | 294 } |
307 ConstantValue constant = _constants.getConstantValueForMetadata(metadata); | 295 |
308 if (addForEmission) { | 296 Iterable<ConstantValue> getClassMetadata(ClassElement element) { |
309 CodegenWorldBuilder worldBuilder = _compiler.codegenWorldBuilder; | 297 return _elementEnvironment.getClassMetadata(element); |
310 worldBuilder.addCompileTimeConstantForEmission(constant); | 298 } |
311 } | 299 |
| 300 Iterable<ConstantValue> getMemberMetadata(MemberEntity element, |
| 301 {bool includeParameterMetadata}) { |
| 302 return _elementEnvironment.getMemberMetadata(element, |
| 303 includeParameterMetadata: includeParameterMetadata); |
| 304 } |
| 305 |
| 306 Iterable<ConstantValue> getTypedefMetadata(TypedefElement element) { |
| 307 return _elementEnvironment.getTypedefMetadata(element); |
| 308 } |
| 309 |
| 310 void _addConstantsForEmission(Iterable<ConstantValue> constants) { |
| 311 for (ConstantValue constant in constants) { |
| 312 CodegenWorldBuilder worldBuilder = _compiler.codegenWorldBuilder; |
| 313 worldBuilder.addCompileTimeConstantForEmission(constant); |
312 } | 314 } |
313 } | 315 } |
314 | 316 |
315 /// Sets of elements that are needed by reflection. Computed using | 317 /// Sets of elements that are needed by reflection. Computed using |
316 /// [computeMembersNeededForReflection] on first use. | 318 /// [computeMembersNeededForReflection] on first use. |
317 Set<ClassElement> _classesNeededForReflection; | 319 Set<ClassEntity> _classesNeededForReflection; |
318 Set<TypedefElement> _typedefsNeededForReflection; | 320 Set<TypedefEntity> _typedefsNeededForReflection; |
319 Set<MemberElement> _membersNeededForReflection; | 321 Set<MemberEntity> _membersNeededForReflection; |
320 Set<LocalFunctionElement> _closuresNeededForReflection; | 322 Set<Local> _closuresNeededForReflection; |
321 | 323 |
322 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed | 324 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed |
323 /// annotations. The arguments corresponds to the unions of the corresponding | 325 /// annotations. The arguments corresponds to the unions of the corresponding |
324 /// fields of the annotations. | 326 /// fields of the annotations. |
325 // TODO(redemption): Change type of [metaTargets] to `Set<ClassEntity>`. | 327 // TODO(redemption): Change type of [metaTargets] to `Set<ClassEntity>`. |
326 void registerMirrorUsage( | 328 void registerMirrorUsage( |
327 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) { | 329 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) { |
328 if (symbols == null && targets == null && metaTargets == null) { | 330 if (symbols == null && targets == null && metaTargets == null) { |
329 // The user didn't specify anything, or there are imports of | 331 // The user didn't specify anything, or there are imports of |
330 // 'dart:mirrors' without @MirrorsUsed. | 332 // 'dart:mirrors' without @MirrorsUsed. |
(...skipping 30 matching lines...) Expand all Loading... |
361 } | 363 } |
362 } | 364 } |
363 } | 365 } |
364 | 366 |
365 @override | 367 @override |
366 bool isClassAccessibleByReflection(ClassEntity element) { | 368 bool isClassAccessibleByReflection(ClassEntity element) { |
367 return _classesNeededForReflection.contains(_getDartClass(element)); | 369 return _classesNeededForReflection.contains(_getDartClass(element)); |
368 } | 370 } |
369 | 371 |
370 @override | 372 @override |
371 bool isTypedefAccessibleByReflection(TypedefElement element) { | 373 bool isTypedefAccessibleByReflection(TypedefEntity element) { |
372 return _typedefsNeededForReflection.contains(element); | 374 return _typedefsNeededForReflection.contains(element); |
373 } | 375 } |
374 | 376 |
375 bool isAccessibleByReflection(Element element) { | |
376 if (element.isLibrary) { | |
377 return false; | |
378 } else if (element.isClass) { | |
379 ClassElement cls = element; | |
380 return isClassAccessibleByReflection(cls); | |
381 } else if (element.isTypedef) { | |
382 return isTypedefAccessibleByReflection(element); | |
383 } else { | |
384 MemberElement member = element; | |
385 return isMemberAccessibleByReflection(member); | |
386 } | |
387 } | |
388 | |
389 ClassEntity _getDartClass(ClassEntity cls) { | 377 ClassEntity _getDartClass(ClassEntity cls) { |
390 if (cls == _commonElements.jsIntClass) { | 378 if (cls == _commonElements.jsIntClass) { |
391 return _commonElements.intClass; | 379 return _commonElements.intClass; |
392 } else if (cls == _commonElements.jsBoolClass) { | 380 } else if (cls == _commonElements.jsBoolClass) { |
393 return _commonElements.boolClass; | 381 return _commonElements.boolClass; |
394 } else if (cls == _commonElements.jsNumberClass) { | 382 } else if (cls == _commonElements.jsNumberClass) { |
395 return _commonElements.numClass; | 383 return _commonElements.numClass; |
396 } else if (cls == _commonElements.jsDoubleClass) { | 384 } else if (cls == _commonElements.jsDoubleClass) { |
397 return _commonElements.doubleClass; | 385 return _commonElements.doubleClass; |
398 } else if (cls == _commonElements.jsStringClass) { | 386 } else if (cls == _commonElements.jsStringClass) { |
399 return _commonElements.stringClass; | 387 return _commonElements.stringClass; |
400 } else if (cls == _commonElements.jsArrayClass) { | 388 } else if (cls == _commonElements.jsArrayClass) { |
401 return _commonElements.listClass; | 389 return _commonElements.listClass; |
402 } else if (cls == _commonElements.jsNullClass) { | 390 } else if (cls == _commonElements.jsNullClass) { |
403 return _commonElements.nullClass; | 391 return _commonElements.nullClass; |
404 } else { | 392 } else { |
405 return cls; | 393 return cls; |
406 } | 394 } |
407 } | 395 } |
408 | 396 |
409 bool isMemberAccessibleByReflection(MemberEntity element) { | 397 bool isMemberAccessibleByReflection(MemberEntity element) { |
410 return _membersNeededForReflection.contains(element); | 398 return _membersNeededForReflection.contains(element); |
411 } | 399 } |
412 | 400 |
413 /// Returns true if this element has to be enqueued due to | 401 /// Returns true if this element has to be enqueued due to |
414 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if | 402 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if |
415 /// normal tree shaking is still active ([isTreeShakingDisabled] is false). | 403 /// normal tree shaking is still active ([isTreeShakingDisabled] is false). |
416 bool requiredByMirrorSystem(Element element) { | 404 bool isLibraryRequiredByMirrorSystem(LibraryEntity element) { |
417 return hasInsufficientMirrorsUsed && isTreeShakingDisabled || | 405 return hasInsufficientMirrorsUsed && isTreeShakingDisabled || |
418 matchesMirrorsMetaTarget(element) || | 406 _libraryMatchesMirrorsMetaTarget(element) || |
419 classesInMirrorsUsedTargets.contains(element) || | 407 librariesInMirrorsUsedTargets.contains(element); |
420 membersInMirrorsUsedTargets.contains(element) || | 408 } |
421 librariesInMirrorsUsedTargets.contains(element) || | 409 |
422 _typedefsInMirrorsUsedTargets.contains(element); | 410 bool isClassRequiredByMirrorSystem(ClassEntity element) { |
| 411 return hasInsufficientMirrorsUsed && isTreeShakingDisabled || |
| 412 _classMatchesMirrorsMetaTarget(element) || |
| 413 classesInMirrorsUsedTargets.contains(element); |
| 414 } |
| 415 |
| 416 bool isMemberRequiredByMirrorSystem(MemberEntity element) { |
| 417 return hasInsufficientMirrorsUsed && isTreeShakingDisabled || |
| 418 _memberMatchesMirrorsMetaTarget(element) || |
| 419 membersInMirrorsUsedTargets.contains(element); |
423 } | 420 } |
424 | 421 |
425 @override | 422 @override |
426 bool isLibraryReferencedFromMirrorSystem(LibraryElement element) { | 423 bool isLibraryReferencedFromMirrorSystem(LibraryEntity element) { |
427 return _libraryReferencedFromMirrorSystem(element); | 424 return _libraryReferencedFromMirrorSystem(element); |
428 } | 425 } |
429 | 426 |
430 @override | 427 @override |
431 bool isMemberReferencedFromMirrorSystem(MemberElement element) { | 428 bool isMemberReferencedFromMirrorSystem(MemberEntity element) { |
432 if (_memberReferencedFromMirrorSystem(element)) return true; | 429 if (_memberReferencedFromMirrorSystem(element)) return true; |
433 if (element.enclosingClass != null) { | 430 if (element.enclosingClass != null) { |
434 return isClassReferencedFromMirrorSystem(element.enclosingClass); | 431 return isClassReferencedFromMirrorSystem(element.enclosingClass); |
435 } else { | 432 } else { |
436 return isLibraryReferencedFromMirrorSystem(element.library); | 433 return isLibraryReferencedFromMirrorSystem(element.library); |
437 } | 434 } |
438 } | 435 } |
439 | 436 |
440 @override | 437 @override |
441 bool isClassReferencedFromMirrorSystem(ClassElement element) { | 438 bool isClassReferencedFromMirrorSystem(ClassEntity element) { |
442 return _classReferencedFromMirrorSystem(element) || | 439 return _classReferencedFromMirrorSystem(element) || |
443 isLibraryReferencedFromMirrorSystem(element.library); | 440 isLibraryReferencedFromMirrorSystem(element.library); |
444 } | 441 } |
445 | 442 |
446 bool isParameterReferencedFromMirrorSystem(ParameterElement element) { | 443 bool _isTypedefReferencedFromMirrorSystem(TypedefEntity element) { |
447 return _parameterReferencedFromMirrorSystem(element) || | |
448 isMemberReferencedFromMirrorSystem(element.memberContext); | |
449 } | |
450 | |
451 bool isTypedefReferencedFromMirrorSystem(TypedefElement element) { | |
452 return _typedefReferencedFromMirrorSystem(element) || | 444 return _typedefReferencedFromMirrorSystem(element) || |
453 isLibraryReferencedFromMirrorSystem(element.library); | 445 isLibraryReferencedFromMirrorSystem(element.library); |
454 } | 446 } |
455 | 447 |
456 bool _memberReferencedFromMirrorSystem(MemberElement element) { | 448 bool _memberReferencedFromMirrorSystem(MemberEntity element) { |
457 return hasInsufficientMirrorsUsed || | 449 return hasInsufficientMirrorsUsed || |
458 matchesMirrorsMetaTarget(element) || | 450 _memberMatchesMirrorsMetaTarget(element) || |
459 membersInMirrorsUsedTargets.contains(element); | 451 membersInMirrorsUsedTargets.contains(element); |
460 } | 452 } |
461 | 453 |
462 bool _parameterReferencedFromMirrorSystem(ParameterElement element) { | 454 bool _classReferencedFromMirrorSystem(ClassEntity element) { |
463 return hasInsufficientMirrorsUsed || matchesMirrorsMetaTarget(element); | |
464 } | |
465 | |
466 bool _classReferencedFromMirrorSystem(ClassElement element) { | |
467 return hasInsufficientMirrorsUsed || | 455 return hasInsufficientMirrorsUsed || |
468 matchesMirrorsMetaTarget(element) || | 456 _classMatchesMirrorsMetaTarget(element) || |
469 classesInMirrorsUsedTargets.contains(element); | 457 classesInMirrorsUsedTargets.contains(element); |
470 } | 458 } |
471 | 459 |
472 bool _typedefReferencedFromMirrorSystem(TypedefElement element) { | 460 bool _typedefReferencedFromMirrorSystem(TypedefEntity element) { |
473 return hasInsufficientMirrorsUsed || | 461 return hasInsufficientMirrorsUsed || |
474 matchesMirrorsMetaTarget(element) || | 462 _typedefMatchesMirrorsMetaTarget(element) || |
475 _typedefsInMirrorsUsedTargets.contains(element); | 463 _typedefsInMirrorsUsedTargets.contains(element); |
476 } | 464 } |
477 | 465 |
478 bool _libraryReferencedFromMirrorSystem(LibraryElement element) { | 466 bool _libraryReferencedFromMirrorSystem(LibraryEntity element) { |
479 return hasInsufficientMirrorsUsed || | 467 return hasInsufficientMirrorsUsed || |
480 matchesMirrorsMetaTarget(element) || | 468 _libraryMatchesMirrorsMetaTarget(element) || |
481 librariesInMirrorsUsedTargets.contains(element); | 469 librariesInMirrorsUsedTargets.contains(element); |
482 } | 470 } |
483 | 471 |
| 472 bool _libraryMatchesMirrorsMetaTarget(LibraryElement element) { |
| 473 if (metaTargetsUsed.isEmpty) return false; |
| 474 return _matchesMirrorsMetaTarget(getLibraryMetadata(element)); |
| 475 } |
| 476 |
| 477 bool _classMatchesMirrorsMetaTarget(ClassEntity element) { |
| 478 if (metaTargetsUsed.isEmpty) return false; |
| 479 return _matchesMirrorsMetaTarget(getClassMetadata(element)); |
| 480 } |
| 481 |
| 482 bool _memberMatchesMirrorsMetaTarget(MemberElement element) { |
| 483 if (metaTargetsUsed.isEmpty) return false; |
| 484 return _matchesMirrorsMetaTarget( |
| 485 getMemberMetadata(element, includeParameterMetadata: false)); |
| 486 } |
| 487 |
| 488 bool _typedefMatchesMirrorsMetaTarget(TypedefElement element) { |
| 489 if (metaTargetsUsed.isEmpty) return false; |
| 490 return _matchesMirrorsMetaTarget(getTypedefMetadata(element)); |
| 491 } |
| 492 |
484 /** | 493 /** |
485 * Returns `true` if the element is needed because it has an annotation | 494 * Returns `true` if the element is needed because it has an annotation |
486 * of a type that is used as a meta target for reflection. | 495 * of a type that is used as a meta target for reflection. |
487 */ | 496 */ |
488 bool matchesMirrorsMetaTarget(Element element) { | 497 bool _matchesMirrorsMetaTarget(Iterable<ConstantValue> constants) { |
489 if (metaTargetsUsed.isEmpty) return false; | 498 if (metaTargetsUsed.isEmpty) return false; |
490 for (MetadataAnnotation metadata in element.metadata) { | 499 for (ConstantValue constant in constants) { |
491 // TODO(kasperl): It would be nice if we didn't have to resolve | 500 DartType type = constant.getType(_commonElements); |
492 // all metadata but only stuff that potentially would match one | |
493 // of the used meta targets. | |
494 metadata.ensureResolved(_compiler.resolution); | |
495 ConstantValue value = | |
496 _compiler.constants.getConstantValue(metadata.constant); | |
497 if (value == null) continue; | |
498 DartType type = value.getType(_commonElements); | |
499 if (type is InterfaceType && metaTargetsUsed.contains(type.element)) | 501 if (type is InterfaceType && metaTargetsUsed.contains(type.element)) |
500 return true; | 502 return true; |
501 } | 503 } |
502 return false; | 504 return false; |
503 } | 505 } |
504 | 506 |
505 void createImmutableSets() { | 507 void createImmutableSets() { |
506 _classesNeededForReflection = const ImmutableEmptySet<ClassElement>(); | 508 _classesNeededForReflection = const ImmutableEmptySet<ClassElement>(); |
507 _typedefsNeededForReflection = const ImmutableEmptySet<TypedefElement>(); | 509 _typedefsNeededForReflection = const ImmutableEmptySet<TypedefElement>(); |
508 _membersNeededForReflection = const ImmutableEmptySet<MemberElement>(); | 510 _membersNeededForReflection = const ImmutableEmptySet<MemberElement>(); |
(...skipping 13 matching lines...) Expand all Loading... |
522 * be visible by reflection unless some other interfaces makes them | 524 * be visible by reflection unless some other interfaces makes them |
523 * accessible. | 525 * accessible. |
524 */ | 526 */ |
525 void computeMembersNeededForReflection( | 527 void computeMembersNeededForReflection( |
526 ResolutionWorldBuilder worldBuilder, ClosedWorld closedWorld) { | 528 ResolutionWorldBuilder worldBuilder, ClosedWorld closedWorld) { |
527 if (_membersNeededForReflection != null) return; | 529 if (_membersNeededForReflection != null) return; |
528 if (!closedWorld.backendUsage.isMirrorsUsed) { | 530 if (!closedWorld.backendUsage.isMirrorsUsed) { |
529 createImmutableSets(); | 531 createImmutableSets(); |
530 return; | 532 return; |
531 } | 533 } |
532 _classesNeededForReflection = new Set<ClassElement>(); | 534 _classesNeededForReflection = new Set<ClassEntity>(); |
533 _typedefsNeededForReflection = new Set<TypedefElement>(); | 535 _typedefsNeededForReflection = new Set<TypedefEntity>(); |
534 _membersNeededForReflection = new Set<MemberElement>(); | 536 _membersNeededForReflection = new Set<MemberEntity>(); |
535 _closuresNeededForReflection = new Set<LocalFunctionElement>(); | 537 _closuresNeededForReflection = new Set<Local>(); |
536 | 538 |
537 // Compute a mapping from class to the closures it contains, so we | 539 // Compute a mapping from class to the closures it contains, so we |
538 // can include the correct ones when including the class. | 540 // can include the correct ones when including the class. |
539 Map<ClassElement, List<LocalFunctionElement>> closureMap = | 541 Map<ClassEntity, List<Local>> closureMap = |
540 new Map<ClassElement, List<LocalFunctionElement>>(); | 542 new Map<ClassEntity, List<Local>>(); |
541 for (LocalFunctionElement closure in worldBuilder.localFunctions) { | 543 for (Local closure in worldBuilder.localFunctions) { |
542 closureMap.putIfAbsent(closure.enclosingClass, () => []).add(closure); | 544 closureMap |
| 545 .putIfAbsent(closure.memberContext.enclosingClass, () => []) |
| 546 .add(closure); |
543 } | 547 } |
544 bool foundClosure = false; | 548 bool foundClosure = false; |
545 for (ClassElement cls in worldBuilder.directlyInstantiatedClasses) { | 549 for (ClassElement cls in worldBuilder.directlyInstantiatedClasses) { |
546 // Do not process internal classes. | 550 // Do not process internal classes. |
547 if (cls.library.isInternalLibrary || cls.isInjected) continue; | 551 if (cls.library.isInternalLibrary || cls.isInjected) continue; |
548 if (isClassReferencedFromMirrorSystem(cls)) { | 552 if (isClassReferencedFromMirrorSystem(cls)) { |
549 Set<Name> memberNames = new Set<Name>(); | 553 Set<Name> memberNames = new Set<Name>(); |
550 // 1) the class (should be resolved) | 554 // 1) the class (should be resolved) |
551 assert(cls.isResolved, failedAt(cls)); | 555 assert(cls.isResolved, failedAt(cls)); |
552 _classesNeededForReflection.add(cls); | 556 _classesNeededForReflection.add(cls); |
(...skipping 27 matching lines...) Expand all Loading... |
580 // assert(worldBuilder.isMemberUsed(member.element), | 584 // assert(worldBuilder.isMemberUsed(member.element), |
581 // failedAt(member.element)); | 585 // failedAt(member.element)); |
582 if (worldBuilder.isMemberUsed(member.element)) { | 586 if (worldBuilder.isMemberUsed(member.element)) { |
583 _membersNeededForReflection.add(member.element); | 587 _membersNeededForReflection.add(member.element); |
584 } | 588 } |
585 } | 589 } |
586 }); | 590 }); |
587 }); | 591 }); |
588 } | 592 } |
589 // 5) all its closures | 593 // 5) all its closures |
590 List<LocalFunctionElement> closures = closureMap[cls]; | 594 List<Local> closures = closureMap[cls]; |
591 if (closures != null) { | 595 if (closures != null) { |
592 _closuresNeededForReflection.addAll(closures); | 596 _closuresNeededForReflection.addAll(closures); |
593 foundClosure = true; | 597 foundClosure = true; |
594 } | 598 } |
595 } else { | 599 } else { |
596 // check members themselves | 600 // check members themselves |
597 cls.constructors.forEach((Element _element) { | 601 cls.constructors.forEach((Element _element) { |
598 ConstructorElement element = _element; | 602 ConstructorElement element = _element; |
599 if (!worldBuilder.isMemberUsed(element)) return; | 603 if (!worldBuilder.isMemberUsed(element)) return; |
600 if (_memberReferencedFromMirrorSystem(element)) { | 604 if (_memberReferencedFromMirrorSystem(element)) { |
601 _membersNeededForReflection.add(element); | 605 _membersNeededForReflection.add(element); |
602 } | 606 } |
603 }); | 607 }); |
604 cls.forEachClassMember((Member member) { | 608 cls.forEachClassMember((Member member) { |
605 if (!worldBuilder.isMemberUsed(member.element)) return; | 609 if (!worldBuilder.isMemberUsed(member.element)) return; |
606 if (_memberReferencedFromMirrorSystem(member.element)) { | 610 if (_memberReferencedFromMirrorSystem(member.element)) { |
607 _membersNeededForReflection.add(member.element); | 611 _membersNeededForReflection.add(member.element); |
608 } | 612 } |
609 }); | 613 }); |
610 // Also add in closures. Those might be reflectable is their enclosing | 614 // Also add in closures. Those might be reflectable is their enclosing |
611 // member is. | 615 // member is. |
612 List<LocalFunctionElement> closures = closureMap[cls]; | 616 List<Local> closures = closureMap[cls]; |
613 if (closures != null) { | 617 if (closures != null) { |
614 for (LocalFunctionElement closure in closures) { | 618 for (Local closure in closures) { |
615 MemberElement member = closure.memberContext; | 619 MemberEntity member = closure.memberContext; |
616 if (_memberReferencedFromMirrorSystem(member)) { | 620 if (_memberReferencedFromMirrorSystem(member)) { |
617 _closuresNeededForReflection.add(closure); | 621 _closuresNeededForReflection.add(closure); |
618 foundClosure = true; | 622 foundClosure = true; |
619 } | 623 } |
620 } | 624 } |
621 } | 625 } |
622 } | 626 } |
623 } | 627 } |
624 // We also need top-level non-class elements like static functions and | 628 // We also need top-level non-class elements like static functions and |
625 // global fields. We use the resolution queue to decide which elements are | 629 // global fields. We use the resolution queue to decide which elements are |
626 // part of the live world. | 630 // part of the live world. |
627 for (LibraryElement lib in _compiler.libraryLoader.libraries) { | 631 for (LibraryElement lib in _compiler.libraryLoader.libraries) { |
628 if (lib.isInternalLibrary) continue; | 632 if (lib.isInternalLibrary) continue; |
629 lib.forEachLocalMember((Element element) { | 633 lib.forEachLocalMember((Element element) { |
630 if (element.isClass || element.isTypedef) return; | 634 if (element.isClass || element.isTypedef) return; |
631 MemberElement member = element; | 635 MemberElement member = element; |
632 if (worldBuilder.isMemberUsed(member) && | 636 if (worldBuilder.isMemberUsed(member) && |
633 isMemberReferencedFromMirrorSystem(member)) { | 637 isMemberReferencedFromMirrorSystem(member)) { |
634 _membersNeededForReflection.add(member); | 638 _membersNeededForReflection.add(member); |
635 } | 639 } |
636 }); | 640 }); |
637 } | 641 } |
638 // And closures inside top-level elements that do not have a surrounding | 642 // And closures inside top-level elements that do not have a surrounding |
639 // class. These will be in the [:null:] bucket of the [closureMap]. | 643 // class. These will be in the [:null:] bucket of the [closureMap]. |
640 if (closureMap.containsKey(null)) { | 644 if (closureMap.containsKey(null)) { |
641 for (LocalFunctionElement closure in closureMap[null]) { | 645 for (Local closure in closureMap[null]) { |
642 if (isMemberReferencedFromMirrorSystem(closure.memberContext)) { | 646 if (isMemberReferencedFromMirrorSystem(closure.memberContext)) { |
643 _closuresNeededForReflection.add(closure); | 647 _closuresNeededForReflection.add(closure); |
644 foundClosure = true; | 648 foundClosure = true; |
645 } | 649 } |
646 } | 650 } |
647 } | 651 } |
648 // As we do not think about closures as classes, yet, we have to make sure | 652 // As we do not think about closures as classes, yet, we have to make sure |
649 // their superclasses are available for reflection manually. | 653 // their superclasses are available for reflection manually. |
650 if (foundClosure) { | 654 if (foundClosure) { |
651 ClassElement cls = _commonElements.closureClass; | 655 ClassEntity cls = _commonElements.closureClass; |
652 _classesNeededForReflection.add(cls); | 656 _classesNeededForReflection.add(cls); |
653 } | 657 } |
654 Set<FunctionEntity> closurizedMembers = worldBuilder.closurizedMembers; | 658 Set<FunctionEntity> closurizedMembers = worldBuilder.closurizedMembers; |
655 if (closurizedMembers.any(_membersNeededForReflection.contains)) { | 659 if (closurizedMembers.any(_membersNeededForReflection.contains)) { |
656 ClassElement cls = _commonElements.boundClosureClass; | 660 ClassEntity cls = _commonElements.boundClosureClass; |
657 _classesNeededForReflection.add(cls); | 661 _classesNeededForReflection.add(cls); |
658 } | 662 } |
659 // Add typedefs. | 663 // Add typedefs. |
660 for (TypedefElement element in closedWorld.allTypedefs) { | 664 for (TypedefEntity element in closedWorld.allTypedefs) { |
661 if (isTypedefReferencedFromMirrorSystem(element)) { | 665 if (_isTypedefReferencedFromMirrorSystem(element)) { |
662 _typedefsNeededForReflection.add(element); | 666 _typedefsNeededForReflection.add(element); |
663 } | 667 } |
664 } | 668 } |
665 // Register all symbols of reflectable elements | 669 // Register all symbols of reflectable elements |
666 for (ClassElement element in _classesNeededForReflection) { | 670 for (ClassEntity element in _classesNeededForReflection) { |
667 symbolsUsed.add(element.name); | 671 symbolsUsed.add(element.name); |
668 } | 672 } |
669 for (TypedefElement element in _typedefsNeededForReflection) { | 673 for (TypedefEntity element in _typedefsNeededForReflection) { |
670 symbolsUsed.add(element.name); | 674 symbolsUsed.add(element.name); |
671 } | 675 } |
672 for (MemberElement element in _membersNeededForReflection) { | 676 for (MemberEntity element in _membersNeededForReflection) { |
673 symbolsUsed.add(element.name); | 677 symbolsUsed.add(element.name); |
674 } | 678 } |
675 for (LocalFunctionElement element in _closuresNeededForReflection) { | 679 for (Local element in _closuresNeededForReflection) { |
676 symbolsUsed.add(element.name); | 680 symbolsUsed.add(element.name); |
677 } | 681 } |
678 } | 682 } |
679 | 683 |
680 // 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 |
681 // [computeMembersNeededForReflection]. | 685 // [computeMembersNeededForReflection]. |
682 void maybeMarkClosureAsNeededForReflection( | 686 void maybeMarkClosureAsNeededForReflection( |
683 ClosureClassElement globalizedElement, | 687 ClosureClassElement globalizedElement, |
684 MethodElement callFunction, | 688 MethodElement callFunction, |
685 LocalFunctionElement function) { | 689 LocalFunctionElement function) { |
686 if (!_closuresNeededForReflection.contains(function)) return; | 690 if (!_closuresNeededForReflection.contains(function)) return; |
687 _membersNeededForReflection.add(callFunction); | 691 _membersNeededForReflection.add(callFunction); |
688 _classesNeededForReflection.add(globalizedElement); | 692 _classesNeededForReflection.add(globalizedElement); |
689 } | 693 } |
690 | 694 |
691 /// Called when `const Symbol(name)` is seen. | 695 /// Called when `const Symbol(name)` is seen. |
692 void registerConstSymbol(String name) { | 696 void registerConstSymbol(String name) { |
693 symbolsUsed.add(name); | 697 symbolsUsed.add(name); |
694 if (name.endsWith('=')) { | 698 if (name.endsWith('=')) { |
695 symbolsUsed.add(name.substring(0, name.length - 1)); | 699 symbolsUsed.add(name.substring(0, name.length - 1)); |
696 } | 700 } |
697 } | 701 } |
698 } | 702 } |
OLD | NEW |