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

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

Issue 2982733002: Use entities in most of MirrorsData (Closed)
Patch Set: Created 3 years, 5 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/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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/mirrors_analysis.dart ('k') | pkg/compiler/lib/src/js_emitter/program_builder/collector.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698