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

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: 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
248 bool retainMetadataOfParameter(ParameterElement element) {
201 if (mustRetainMetadata) hasRetainedMetadata = true; 249 if (mustRetainMetadata) hasRetainedMetadata = true;
202 if (mustRetainMetadata && referencedFromMirrorSystem(element)) { 250 if (mustRetainMetadata && isParameterReferencedFromMirrorSystem(element)) {
203 for (MetadataAnnotation metadata in element.metadata) { 251 _retainMetadataOf(element);
204 metadata.ensureResolved(_compiler.resolution);
205 ConstantValue constant =
206 _constants.getConstantValueForMetadata(metadata);
207 _constants.addCompileTimeConstantForEmission(constant);
208 }
209 return true; 252 return true;
210 } 253 }
211 return false; 254 return false;
212 } 255 }
213 256
257 @override
258 bool retainMetadataOfMember(MemberElement element) {
259 if (mustRetainMetadata) hasRetainedMetadata = true;
260 if (mustRetainMetadata && isMemberReferencedFromMirrorSystem(element)) {
Emily Fortuna 2017/04/04 18:27:13 any reason you don't write this as a nested loop l
Johnni Winther 2017/04/05 06:59:58 No _good_ reason. Changed.
261 _retainMetadataOf(element);
262 return true;
263 }
264 return false;
265 }
266
267 @override
268 bool retainMetadataOfClass(ClassElement element) {
269 if (mustRetainMetadata) hasRetainedMetadata = true;
270 if (mustRetainMetadata && isClassReferencedFromMirrorSystem(element)) {
271 _retainMetadataOf(element);
272 return true;
273 }
274 return false;
275 }
276
277 @override
278 bool retainMetadataOfTypedef(TypedefElement element) {
279 if (mustRetainMetadata) hasRetainedMetadata = true;
280 if (mustRetainMetadata && isTypedefReferencedFromMirrorSystem(element)) {
281 _retainMetadataOf(element);
282 return true;
283 }
284 return false;
285 }
286
287 @override
288 bool retainMetadataOfLibrary(LibraryElement element) {
289 if (mustRetainMetadata) hasRetainedMetadata = true;
290 if (mustRetainMetadata && isLibraryReferencedFromMirrorSystem(element)) {
291 _retainMetadataOf(element);
292 return true;
293 }
294 return false;
295 }
296
297 void _retainMetadataOf(Element element) {
298 for (MetadataAnnotation metadata in element.metadata) {
299 metadata.ensureResolved(_compiler.resolution);
300 ConstantValue constant = _constants.getConstantValueForMetadata(metadata);
301 _constants.addCompileTimeConstantForEmission(constant);
302 }
303 }
304
214 bool invokedReflectively(Element element) { 305 bool invokedReflectively(Element element) {
215 if (element.isParameter) { 306 if (element.isParameter) {
216 ParameterElement parameter = element; 307 ParameterElement parameter = element;
217 if (invokedReflectively(parameter.functionDeclaration)) return true; 308 if (invokedReflectively(parameter.functionDeclaration)) return true;
218 } 309 }
219 310
220 if (element.isField) { 311 if (element.isField) {
221 if (Elements.isStaticOrTopLevel(element) && 312 if (Elements.isStaticOrTopLevel(element) &&
222 (element.isFinal || element.isConst)) { 313 (element.isFinal || element.isConst)) {
223 return false; 314 return false;
224 } 315 }
225 } 316 }
226 317
227 return isAccessibleByReflection(element.declaration); 318 return isAccessibleByReflection(element.declaration);
228 } 319 }
229 320
230 /// Set of methods that are needed by reflection. Computed using 321 /// Sets of elements that are needed by reflection. Computed using
231 /// [computeMembersNeededForReflection] on first use. 322 /// [computeMembersNeededForReflection] on first use.
232 Set<Element> _membersNeededForReflection = null; 323 Set<ClassElement> _classesNeededForReflection;
233 Iterable<Element> get membersNeededForReflection { 324 Set<TypedefElement> _typedefsNeededForReflection;
234 assert(_membersNeededForReflection != null); 325 Set<MemberElement> _membersNeededForReflection;
235 return _membersNeededForReflection; 326 Set<LocalFunctionElement> _closuresNeededForReflection;
236 }
237 327
238 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed 328 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed
239 /// annotations. The arguments corresponds to the unions of the corresponding 329 /// annotations. The arguments corresponds to the unions of the corresponding
240 /// fields of the annotations. 330 /// fields of the annotations.
331 // TODO(johnniwinther): Change type of [metaTargets] to `Set<ClassEntity>`.
241 void registerMirrorUsage( 332 void registerMirrorUsage(
242 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) { 333 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) {
243 if (symbols == null && targets == null && metaTargets == null) { 334 if (symbols == null && targets == null && metaTargets == null) {
244 // The user didn't specify anything, or there are imports of 335 // The user didn't specify anything, or there are imports of
245 // 'dart:mirrors' without @MirrorsUsed. 336 // 'dart:mirrors' without @MirrorsUsed.
246 hasInsufficientMirrorsUsed = true; 337 hasInsufficientMirrorsUsed = true;
247 return; 338 return;
248 } 339 }
249 if (symbols != null) symbolsUsed.addAll(symbols); 340 if (symbols != null) symbolsUsed.addAll(symbols);
250 if (targets != null) { 341 if (targets != null) {
251 for (Element target in targets) { 342 for (Element target in targets) {
252 if (target.isAbstractField) { 343 if (target.isAbstractField) {
253 AbstractFieldElement field = target; 344 AbstractFieldElement field = target;
254 targetsUsed.add(field.getter); 345 if (field.getter != null) {
255 targetsUsed.add(field.setter); 346 membersInMirrorsUsedTargets.add(field.getter);
256 } else { 347 }
257 targetsUsed.add(target); 348 if (field.setter != null) {
349 membersInMirrorsUsedTargets.add(field.setter);
350 }
351 } else if (target.isClass) {
352 classesInMirrorsUsedTargets.add(target as ClassEntity);
353 } else if (target.isTypedef) {
354 _typedefsInMirrorsUsedTargets.add(target);
355 } else if (target.isLibrary) {
356 librariesInMirrorsUsedTargets.add(target as LibraryEntity);
357 } else if (target != null) {
358 membersInMirrorsUsedTargets.add(target as MemberEntity);
258 } 359 }
259 } 360 }
260 } 361 }
261 if (metaTargets != null) metaTargetsUsed.addAll(metaTargets); 362 if (metaTargets != null) {
363 for (var element in metaTargets) {
364 if (element is ClassEntity) {
365 metaTargetsUsed.add(element);
366 }
367 }
368 }
262 } 369 }
263 370
264 /// Returns `true` if [element] can be accessed through reflection, that is, 371 @override
265 /// is in the set of elements covered by a `MirrorsUsed` annotation. 372 bool isClassAccessibleByReflection(ClassElement element) {
266 /// 373 return _classesNeededForReflection.contains(_getDartClass(element));
267 /// This property is used to tag emitted elements with a marker which is 374 }
268 /// checked by the runtime system to throw an exception if an element is 375
269 /// accessed (invoked, get, set) that is not accessible for the reflective 376 @override
270 /// system. 377 bool isTypedefAccessibleByReflection(TypedefElement element) {
378 return _typedefsNeededForReflection.contains(element);
379 }
380
271 bool isAccessibleByReflection(Element element) { 381 bool isAccessibleByReflection(Element element) {
272 if (element.isClass) { 382 if (element.isLibrary) {
273 element = _getDartClass(element); 383 return false;
384 } else if (element.isClass) {
385 return isClassAccessibleByReflection(element);
386 } else if (element.isTypedef) {
387 return isTypedefAccessibleByReflection(element);
388 } else {
389 return isMemberAccessibleByReflection(element);
274 } 390 }
275 return membersNeededForReflection.contains(element);
276 } 391 }
277 392
278 ClassElement _getDartClass(ClassElement cls) { 393 ClassElement _getDartClass(ClassElement cls) {
279 if (cls == _helpers.jsIntClass) { 394 if (cls == _helpers.jsIntClass) {
280 return _commonElements.intClass; 395 return _commonElements.intClass;
281 } else if (cls == _helpers.jsBoolClass) { 396 } else if (cls == _helpers.jsBoolClass) {
282 return _commonElements.boolClass; 397 return _commonElements.boolClass;
283 } else if (cls == _helpers.jsNumberClass) { 398 } else if (cls == _helpers.jsNumberClass) {
284 return _commonElements.numClass; 399 return _commonElements.numClass;
285 } else if (cls == _helpers.jsDoubleClass) { 400 } else if (cls == _helpers.jsDoubleClass) {
286 return _commonElements.doubleClass; 401 return _commonElements.doubleClass;
287 } else if (cls == _helpers.jsStringClass) { 402 } else if (cls == _helpers.jsStringClass) {
288 return _commonElements.stringClass; 403 return _commonElements.stringClass;
289 } else if (cls == _helpers.jsArrayClass) { 404 } else if (cls == _helpers.jsArrayClass) {
290 return _commonElements.listClass; 405 return _commonElements.listClass;
291 } else if (cls == _helpers.jsNullClass) { 406 } else if (cls == _helpers.jsNullClass) {
292 return _commonElements.nullClass; 407 return _commonElements.nullClass;
293 } else { 408 } else {
294 return cls; 409 return cls;
295 } 410 }
296 } 411 }
297 412
298 /// Returns `true` if this member element needs reflection information at
299 /// runtime.
300 bool isMemberAccessibleByReflection(MemberElement element) { 413 bool isMemberAccessibleByReflection(MemberElement element) {
301 return membersNeededForReflection.contains(element); 414 return _membersNeededForReflection.contains(element);
302 } 415 }
303 416
304 /// Returns true if this element has to be enqueued due to 417 /// Returns true if this element has to be enqueued due to
305 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if 418 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if
306 /// normal tree shaking is still active ([isTreeShakingDisabled] is false). 419 /// normal tree shaking is still active ([isTreeShakingDisabled] is false).
307 bool requiredByMirrorSystem(Element element) { 420 bool requiredByMirrorSystem(Element element) {
308 return hasInsufficientMirrorsUsed && isTreeShakingDisabled || 421 return hasInsufficientMirrorsUsed && isTreeShakingDisabled ||
309 matchesMirrorsMetaTarget(element) || 422 matchesMirrorsMetaTarget(element) ||
310 targetsUsed.contains(element); 423 classesInMirrorsUsedTargets.contains(element) ||
424 membersInMirrorsUsedTargets.contains(element) ||
425 librariesInMirrorsUsedTargets.contains(element) ||
426 _typedefsInMirrorsUsedTargets.contains(element);
311 } 427 }
312 428
313 /// Returns true if this element is covered by a mirrorsUsed annotation. 429 @override
314 /// 430 bool isLibraryReferencedFromMirrorSystem(LibraryElement element) {
315 /// Note that it might still be ok to tree shake the element away if no 431 return _libraryReferencedFromMirrorSystem(element);
316 /// reflection is used in the program (and thus [isTreeShakingDisabled] is 432 }
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 433
434 @override
435 bool isMemberReferencedFromMirrorSystem(MemberElement element) {
436 if (_memberReferencedFromMirrorSystem(element)) return true;
437 if (element.enclosingClass != null) {
438 return isClassReferencedFromMirrorSystem(element.enclosingClass);
439 } else {
440 return isLibraryReferencedFromMirrorSystem(element.library);
441 }
442 }
443
444 @override
445 bool isClassReferencedFromMirrorSystem(ClassElement element) {
446 return _classReferencedFromMirrorSystem(element) ||
447 isLibraryReferencedFromMirrorSystem(element.library);
448 }
449
450 bool isParameterReferencedFromMirrorSystem(ParameterElement element) {
451 return _parameterReferencedFromMirrorSystem(element) ||
452 isMemberReferencedFromMirrorSystem(element.memberContext);
453 }
454
455 bool isTypedefReferencedFromMirrorSystem(TypedefElement element) {
456 return _typedefReferencedFromMirrorSystem(element) ||
457 isLibraryReferencedFromMirrorSystem(element.library);
458 }
459
460 bool _memberReferencedFromMirrorSystem(MemberElement element) {
322 return hasInsufficientMirrorsUsed || 461 return hasInsufficientMirrorsUsed ||
323 matchesMirrorsMetaTarget(element) || 462 matchesMirrorsMetaTarget(element) ||
324 targetsUsed.contains(element) || 463 membersInMirrorsUsedTargets.contains(element);
325 (enclosing != null && referencedFromMirrorSystem(enclosing)); 464 }
465
466 bool _parameterReferencedFromMirrorSystem(ParameterElement element) {
467 return hasInsufficientMirrorsUsed || matchesMirrorsMetaTarget(element);
468 }
469
470 bool _classReferencedFromMirrorSystem(ClassElement element) {
471 return hasInsufficientMirrorsUsed ||
472 matchesMirrorsMetaTarget(element) ||
473 classesInMirrorsUsedTargets.contains(element);
474 }
475
476 bool _typedefReferencedFromMirrorSystem(TypedefElement element) {
477 return hasInsufficientMirrorsUsed ||
478 matchesMirrorsMetaTarget(element) ||
479 _typedefsInMirrorsUsedTargets.contains(element);
480 }
481
482 bool _libraryReferencedFromMirrorSystem(LibraryElement element) {
483 return hasInsufficientMirrorsUsed ||
484 matchesMirrorsMetaTarget(element) ||
485 librariesInMirrorsUsedTargets.contains(element);
326 } 486 }
327 487
328 /** 488 /**
329 * Returns `true` if the element is needed because it has an annotation 489 * 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. 490 * of a type that is used as a meta target for reflection.
331 */ 491 */
332 bool matchesMirrorsMetaTarget(Element element) { 492 bool matchesMirrorsMetaTarget(Element element) {
333 if (metaTargetsUsed.isEmpty) return false; 493 if (metaTargetsUsed.isEmpty) return false;
334 for (MetadataAnnotation metadata in element.metadata) { 494 for (MetadataAnnotation metadata in element.metadata) {
335 // TODO(kasperl): It would be nice if we didn't have to resolve 495 // TODO(kasperl): It would be nice if we didn't have to resolve
336 // all metadata but only stuff that potentially would match one 496 // all metadata but only stuff that potentially would match one
337 // of the used meta targets. 497 // of the used meta targets.
338 metadata.ensureResolved(_compiler.resolution); 498 metadata.ensureResolved(_compiler.resolution);
339 ConstantValue value = 499 ConstantValue value =
340 _compiler.constants.getConstantValue(metadata.constant); 500 _compiler.constants.getConstantValue(metadata.constant);
341 if (value == null) continue; 501 if (value == null) continue;
342 ResolutionDartType type = value.getType(_commonElements); 502 DartType type = value.getType(_commonElements);
343 if (metaTargetsUsed.contains(type.element)) return true; 503 if (type is InterfaceType && metaTargetsUsed.contains(type.element))
504 return true;
344 } 505 }
345 return false; 506 return false;
346 } 507 }
347 508
348 /** 509 /**
349 * Visits all classes and computes whether its members are needed for 510 * Visits all classes and computes whether its members are needed for
350 * reflection. 511 * reflection.
351 * 512 *
352 * We have to precompute this set as we cannot easily answer the need for 513 * 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 514 * reflection locally when looking at the member: We lack the information by
354 * which classes a member is inherited. Called after resolution is complete. 515 * which classes a member is inherited. Called after resolution is complete.
355 * 516 *
356 * We filter out private libraries here, as their elements should not 517 * We filter out private libraries here, as their elements should not
357 * be visible by reflection unless some other interfaces makes them 518 * be visible by reflection unless some other interfaces makes them
358 * accessible. 519 * accessible.
359 */ 520 */
360 void computeMembersNeededForReflection( 521 void computeMembersNeededForReflection(
361 ResolutionWorldBuilder worldBuilder, ClosedWorld closedWorld) { 522 ResolutionWorldBuilder worldBuilder, ClosedWorld closedWorld) {
362 if (_membersNeededForReflection != null) return; 523 if (_membersNeededForReflection != null) return;
363 if (closedWorld.commonElements.mirrorsLibrary == null) { 524 if (closedWorld.commonElements.mirrorsLibrary == null) {
364 _membersNeededForReflection = const ImmutableEmptySet<Element>(); 525 _classesNeededForReflection = const ImmutableEmptySet<ClassElement>();
526 _typedefsNeededForReflection = const ImmutableEmptySet<TypedefElement>();
527 _membersNeededForReflection = const ImmutableEmptySet<MemberElement>();
528 _closuresNeededForReflection =
529 const ImmutableEmptySet<LocalFunctionElement>();
365 return; 530 return;
366 } 531 }
532 _classesNeededForReflection = new Set<ClassElement>();
533 _typedefsNeededForReflection = new Set<TypedefElement>();
534 _membersNeededForReflection = new Set<MemberElement>();
535 _closuresNeededForReflection = new Set<LocalFunctionElement>();
536
367 // Compute a mapping from class to the closures it contains, so we 537 // Compute a mapping from class to the closures it contains, so we
368 // can include the correct ones when including the class. 538 // can include the correct ones when including the class.
369 Map<ClassElement, List<LocalFunctionElement>> closureMap = 539 Map<ClassElement, List<LocalFunctionElement>> closureMap =
370 new Map<ClassElement, List<LocalFunctionElement>>(); 540 new Map<ClassElement, List<LocalFunctionElement>>();
371 for (LocalFunctionElement closure in worldBuilder.localFunctions) { 541 for (LocalFunctionElement closure in worldBuilder.localFunctions) {
372 closureMap.putIfAbsent(closure.enclosingClass, () => []).add(closure); 542 closureMap.putIfAbsent(closure.enclosingClass, () => []).add(closure);
373 } 543 }
374 bool foundClosure = false; 544 bool foundClosure = false;
375 Set<Element> reflectableMembers = new Set<Element>();
376 for (ClassElement cls in worldBuilder.directlyInstantiatedClasses) { 545 for (ClassElement cls in worldBuilder.directlyInstantiatedClasses) {
377 // Do not process internal classes. 546 // Do not process internal classes.
378 if (cls.library.isInternalLibrary || cls.isInjected) continue; 547 if (cls.library.isInternalLibrary || cls.isInjected) continue;
379 if (referencedFromMirrorSystem(cls)) { 548 if (isClassReferencedFromMirrorSystem(cls)) {
380 Set<Name> memberNames = new Set<Name>(); 549 Set<Name> memberNames = new Set<Name>();
381 // 1) the class (should be resolved) 550 // 1) the class (should be resolved)
382 assert(invariant(cls, cls.isResolved)); 551 assert(invariant(cls, cls.isResolved));
383 reflectableMembers.add(cls); 552 _classesNeededForReflection.add(cls);
384 // 2) its constructors (if resolved) 553 // 2) its constructors (if resolved)
385 cls.constructors.forEach((ConstructorElement constructor) { 554 cls.constructors.forEach((ConstructorElement constructor) {
386 if (worldBuilder.isMemberUsed(constructor)) { 555 if (worldBuilder.isMemberUsed(constructor)) {
387 reflectableMembers.add(constructor); 556 _membersNeededForReflection.add(constructor);
388 } 557 }
389 }); 558 });
390 // 3) all members, including fields via getter/setters (if resolved) 559 // 3) all members, including fields via getter/setters (if resolved)
391 cls.forEachClassMember((Member member) { 560 cls.forEachClassMember((Member member) {
392 MemberElement element = member.element; 561 MemberElement element = member.element;
393 if (worldBuilder.isMemberUsed(element)) { 562 if (worldBuilder.isMemberUsed(element)) {
394 memberNames.add(member.name); 563 memberNames.add(member.name);
395 reflectableMembers.add(element); 564 _membersNeededForReflection.add(element);
396 element.nestedClosures 565 element.nestedClosures
397 .forEach((SynthesizedCallMethodElementX callFunction) { 566 .forEach((SynthesizedCallMethodElementX callFunction) {
398 reflectableMembers.add(callFunction); 567 _membersNeededForReflection.add(callFunction);
399 reflectableMembers.add(callFunction.closureClass); 568 _classesNeededForReflection.add(callFunction.closureClass);
400 }); 569 });
401 } 570 }
402 }); 571 });
403 // 4) all overriding members of subclasses/subtypes (should be resolved) 572 // 4) all overriding members of subclasses/subtypes (should be resolved)
404 if (closedWorld.hasAnyStrictSubtype(cls)) { 573 if (closedWorld.hasAnyStrictSubtype(cls)) {
405 closedWorld.forEachStrictSubtypeOf(cls, (ClassElement subcls) { 574 closedWorld.forEachStrictSubtypeOf(cls, (ClassElement subcls) {
406 subcls.forEachClassMember((Member member) { 575 subcls.forEachClassMember((Member member) {
407 if (memberNames.contains(member.name)) { 576 if (memberNames.contains(member.name)) {
408 // TODO(20993): find out why this assertion fails. 577 // TODO(20993): find out why this assertion fails.
409 // assert(invariant(member.element, 578 // assert(invariant(member.element,
410 // worldBuilder.isMemberUsed(member.element))); 579 // worldBuilder.isMemberUsed(member.element)));
411 if (worldBuilder.isMemberUsed(member.element)) { 580 if (worldBuilder.isMemberUsed(member.element)) {
412 reflectableMembers.add(member.element); 581 _membersNeededForReflection.add(member.element);
413 } 582 }
414 } 583 }
415 }); 584 });
416 }); 585 });
417 } 586 }
418 // 5) all its closures 587 // 5) all its closures
419 List<LocalFunctionElement> closures = closureMap[cls]; 588 List<LocalFunctionElement> closures = closureMap[cls];
420 if (closures != null) { 589 if (closures != null) {
421 reflectableMembers.addAll(closures); 590 _closuresNeededForReflection.addAll(closures);
422 foundClosure = true; 591 foundClosure = true;
423 } 592 }
424 } else { 593 } else {
425 // check members themselves 594 // check members themselves
426 cls.constructors.forEach((ConstructorElement element) { 595 cls.constructors.forEach((ConstructorElement element) {
427 if (!worldBuilder.isMemberUsed(element)) return; 596 if (!worldBuilder.isMemberUsed(element)) return;
428 if (referencedFromMirrorSystem(element, false)) { 597 if (_memberReferencedFromMirrorSystem(element)) {
429 reflectableMembers.add(element); 598 _membersNeededForReflection.add(element);
430 } 599 }
431 }); 600 });
432 cls.forEachClassMember((Member member) { 601 cls.forEachClassMember((Member member) {
433 if (!worldBuilder.isMemberUsed(member.element)) return; 602 if (!worldBuilder.isMemberUsed(member.element)) return;
434 if (referencedFromMirrorSystem(member.element, false)) { 603 if (_memberReferencedFromMirrorSystem(member.element)) {
435 reflectableMembers.add(member.element); 604 _membersNeededForReflection.add(member.element);
436 } 605 }
437 }); 606 });
438 // Also add in closures. Those might be reflectable is their enclosing 607 // Also add in closures. Those might be reflectable is their enclosing
439 // member is. 608 // member is.
440 List<LocalFunctionElement> closures = closureMap[cls]; 609 List<LocalFunctionElement> closures = closureMap[cls];
441 if (closures != null) { 610 if (closures != null) {
442 for (LocalFunctionElement closure in closures) { 611 for (LocalFunctionElement closure in closures) {
443 MemberElement member = closure.memberContext; 612 MemberElement member = closure.memberContext;
444 if (referencedFromMirrorSystem(member, false)) { 613 if (_memberReferencedFromMirrorSystem(member)) {
445 reflectableMembers.add(closure); 614 _closuresNeededForReflection.add(closure);
446 foundClosure = true; 615 foundClosure = true;
447 } 616 }
448 } 617 }
449 } 618 }
450 } 619 }
451 } 620 }
452 // We also need top-level non-class elements like static functions and 621 // 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 622 // global fields. We use the resolution queue to decide which elements are
454 // part of the live world. 623 // part of the live world.
455 for (LibraryElement lib in _compiler.libraryLoader.libraries) { 624 for (LibraryElement lib in _compiler.libraryLoader.libraries) {
456 if (lib.isInternalLibrary) continue; 625 if (lib.isInternalLibrary) continue;
457 lib.forEachLocalMember((Element element) { 626 lib.forEachLocalMember((Element element) {
458 if (element.isClass || element.isTypedef) return; 627 if (element.isClass || element.isTypedef) return;
459 MemberElement member = element; 628 MemberElement member = element;
460 if (worldBuilder.isMemberUsed(member) && 629 if (worldBuilder.isMemberUsed(member) &&
461 referencedFromMirrorSystem(member)) { 630 isMemberReferencedFromMirrorSystem(member)) {
462 reflectableMembers.add(member); 631 _membersNeededForReflection.add(member);
463 } 632 }
464 }); 633 });
465 } 634 }
466 // And closures inside top-level elements that do not have a surrounding 635 // And closures inside top-level elements that do not have a surrounding
467 // class. These will be in the [:null:] bucket of the [closureMap]. 636 // class. These will be in the [:null:] bucket of the [closureMap].
468 if (closureMap.containsKey(null)) { 637 if (closureMap.containsKey(null)) {
469 for (Element closure in closureMap[null]) { 638 for (LocalFunctionElement closure in closureMap[null]) {
470 if (referencedFromMirrorSystem(closure)) { 639 if (isMemberReferencedFromMirrorSystem(closure.memberContext)) {
471 reflectableMembers.add(closure); 640 _closuresNeededForReflection.add(closure);
472 foundClosure = true; 641 foundClosure = true;
473 } 642 }
474 } 643 }
475 } 644 }
476 // As we do not think about closures as classes, yet, we have to make sure 645 // As we do not think about closures as classes, yet, we have to make sure
477 // their superclasses are available for reflection manually. 646 // their superclasses are available for reflection manually.
478 if (foundClosure) { 647 if (foundClosure) {
479 ClassElement cls = _helpers.closureClass; 648 ClassElement cls = _helpers.closureClass;
480 reflectableMembers.add(cls); 649 _classesNeededForReflection.add(cls);
481 } 650 }
482 Set<MethodElement> closurizedMembers = worldBuilder.closurizedMembers; 651 Set<MethodElement> closurizedMembers = worldBuilder.closurizedMembers;
483 if (closurizedMembers.any(reflectableMembers.contains)) { 652 if (closurizedMembers.any(_membersNeededForReflection.contains)) {
484 ClassElement cls = _helpers.boundClosureClass; 653 ClassElement cls = _helpers.boundClosureClass;
485 reflectableMembers.add(cls); 654 _classesNeededForReflection.add(cls);
486 } 655 }
487 // Add typedefs. 656 // Add typedefs.
488 reflectableMembers 657 _typedefsNeededForReflection.addAll(
489 .addAll(closedWorld.allTypedefs.where(referencedFromMirrorSystem)); 658 closedWorld.allTypedefs.where(isTypedefReferencedFromMirrorSystem));
490 // Register all symbols of reflectable elements 659 // Register all symbols of reflectable elements
491 for (Element element in reflectableMembers) { 660 for (ClassElement element in _classesNeededForReflection) {
492 symbolsUsed.add(element.name); 661 symbolsUsed.add(element.name);
493 } 662 }
494 _membersNeededForReflection = reflectableMembers; 663 for (TypedefElement element in _typedefsNeededForReflection) {
664 symbolsUsed.add(element.name);
665 }
666 for (MemberElement element in _membersNeededForReflection) {
667 symbolsUsed.add(element.name);
668 }
669 for (LocalFunctionElement element in _closuresNeededForReflection) {
670 symbolsUsed.add(element.name);
671 }
495 } 672 }
496 673
497 // TODO(20791): compute closure classes after resolution and move this code to 674 // TODO(20791): compute closure classes after resolution and move this code to
498 // [computeMembersNeededForReflection]. 675 // [computeMembersNeededForReflection].
499 void maybeMarkClosureAsNeededForReflection( 676 void maybeMarkClosureAsNeededForReflection(
500 ClosureClassElement globalizedElement, 677 ClosureClassElement globalizedElement,
501 FunctionElement callFunction, 678 MethodElement callFunction,
502 FunctionElement function) { 679 LocalFunctionElement function) {
503 if (!_membersNeededForReflection.contains(function)) return; 680 if (!_closuresNeededForReflection.contains(function)) return;
504 _membersNeededForReflection.add(callFunction); 681 _membersNeededForReflection.add(callFunction);
505 _membersNeededForReflection.add(globalizedElement); 682 _classesNeededForReflection.add(globalizedElement);
506 } 683 }
507 684
508 /// Called when `const Symbol(name)` is seen. 685 /// Called when `const Symbol(name)` is seen.
509 void registerConstSymbol(String name) { 686 void registerConstSymbol(String name) {
510 symbolsUsed.add(name); 687 symbolsUsed.add(name);
511 if (name.endsWith('=')) { 688 if (name.endsWith('=')) {
512 symbolsUsed.add(name.substring(0, name.length - 1)); 689 symbolsUsed.add(name.substring(0, name.length - 1));
513 } 690 }
514 } 691 }
515 } 692 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698