| 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/resolution_types.dart'; | 11 import '../elements/resolution_types.dart'; |
| 12 import '../options.dart'; | 12 import '../options.dart'; |
| 13 import '../world.dart'; | 13 import '../world.dart'; |
| 14 import '../universe/world_builder.dart'; | 14 import '../universe/world_builder.dart'; |
| 15 import '../util/emptyset.dart'; | 15 import '../util/emptyset.dart'; |
| 16 import 'backend_helpers.dart'; | 16 import 'backend_helpers.dart'; |
| 17 import 'constant_handler_javascript.dart'; | 17 import 'constant_handler_javascript.dart'; |
| 18 | 18 |
| 19 class MirrorsData { | 19 abstract class MirrorsData { |
| 20 /// True if a call to preserveMetadataMarker has been seen. This means that |
| 21 /// metadata must be retained for dart:mirrors to work correctly. |
| 22 // resolution-empty-queue |
| 23 bool get mustRetainMetadata; |
| 24 |
| 25 /// True if any metadata has been retained. This is slightly different from |
| 26 /// [mustRetainMetadata] and tells us if any metadata was retained. For |
| 27 /// example, if [mustRetainMetadata] is true but there is no metadata in the |
| 28 /// program, this variable will stil be false. |
| 29 // emitter |
| 30 bool get hasRetainedMetadata; |
| 31 |
| 32 /// True if a call to preserveLibraryNames has been seen. |
| 33 // emitter |
| 34 bool get mustRetainLibraryNames; |
| 35 |
| 36 /// True if a call to preserveNames has been seen. |
| 37 // resolution-empty-queue |
| 38 bool get mustPreserveNames; |
| 39 |
| 40 /// True if a call to disableTreeShaking has been seen. |
| 41 bool get isTreeShakingDisabled; |
| 42 |
| 43 /// True if a call to preserveUris has been seen and the preserve-uris flag |
| 44 /// is set. |
| 45 bool get mustPreserveUris; |
| 46 |
| 47 /// Set of symbols that the user has requested for reflection. |
| 48 Iterable<String> get symbolsUsed; |
| 49 |
| 50 /// Set of elements that the user has requested for reflection. |
| 51 Iterable<Element> get targetsUsed; |
| 52 |
| 53 /// Should [element] (a getter) that would normally not be generated due to |
| 54 /// treeshaking be retained for reflection? |
| 55 bool shouldRetainGetter(Element element); |
| 56 |
| 57 /// Should [element] (a setter) hat would normally not be generated due to |
| 58 /// treeshaking be retained for reflection? |
| 59 bool shouldRetainSetter(Element element); |
| 60 |
| 61 /// Should [name] be retained for reflection? |
| 62 bool shouldRetainName(String name); |
| 63 |
| 64 /// Returns true if this element is covered by a mirrorsUsed annotation. |
| 65 /// |
| 66 /// 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 |
| 68 /// still false). Therefore _do not_ use this predicate to decide inclusion |
| 69 /// in the tree, use [requiredByMirrorSystem] instead. |
| 70 bool referencedFromMirrorSystem(Element element, [recursive = true]); |
| 71 |
| 72 /// Returns `true` if [element] can be accessed through reflection, that is, |
| 73 /// is in the set of elements covered by a `MirrorsUsed` annotation. |
| 74 /// |
| 75 /// 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 |
| 77 /// accessed (invoked, get, set) that is not accessible for the reflective |
| 78 /// system. |
| 79 bool isAccessibleByReflection(Element element); |
| 80 |
| 81 bool retainMetadataOf(Element element); |
| 82 |
| 83 bool invokedReflectively(Element element); |
| 84 |
| 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 |
| 90 /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if |
| 91 /// normal tree shaking is still active ([isTreeShakingDisabled] is false). |
| 92 bool requiredByMirrorSystem(Element element); |
| 93 } |
| 94 |
| 95 abstract class MirrorsDataBuilder { |
| 96 void registerUsedMember(MemberElement member); |
| 97 |
| 98 /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed |
| 99 /// annotations. The arguments corresponds to the unions of the corresponding |
| 100 /// fields of the annotations. |
| 101 void registerMirrorUsage( |
| 102 Set<String> symbols, Set<Element> targets, Set<Element> metaTargets); |
| 103 |
| 104 /// Called when `const Symbol(name)` is seen. |
| 105 void registerConstSymbol(String name); |
| 106 |
| 107 void maybeMarkClosureAsNeededForReflection( |
| 108 ClosureClassElement globalizedElement, |
| 109 FunctionElement callFunction, |
| 110 FunctionElement function); |
| 111 |
| 112 void computeMembersNeededForReflection( |
| 113 ResolutionWorldBuilder worldBuilder, ClosedWorld closedWorld); |
| 114 } |
| 115 |
| 116 class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| 20 /// True if a call to preserveMetadataMarker has been seen. This means that | 117 /// True if a call to preserveMetadataMarker has been seen. This means that |
| 21 /// metadata must be retained for dart:mirrors to work correctly. | 118 /// metadata must be retained for dart:mirrors to work correctly. |
| 22 bool mustRetainMetadata = false; | 119 bool mustRetainMetadata = false; |
| 23 | 120 |
| 24 /// True if any metadata has been retained. This is slightly different from | 121 /// True if any metadata has been retained. This is slightly different from |
| 25 /// [mustRetainMetadata] and tells us if any metadata was retained. For | 122 /// [mustRetainMetadata] and tells us if any metadata was retained. For |
| 26 /// example, if [mustRetainMetadata] is true but there is no metadata in the | 123 /// example, if [mustRetainMetadata] is true but there is no metadata in the |
| 27 /// program, this variable will stil be false. | 124 /// program, this variable will stil be false. |
| 28 bool hasRetainedMetadata = false; | 125 bool hasRetainedMetadata = false; |
| 29 | 126 |
| 30 /// True if a call to preserveLibraryNames has been seen. | 127 /// True if a call to preserveLibraryNames has been seen. |
| 31 bool mustRetainLibraryNames = false; | 128 bool mustRetainLibraryNames = false; |
| 32 | 129 |
| 33 /// True if a call to preserveNames has been seen. | 130 /// True if a call to preserveNames has been seen. |
| 34 bool mustPreserveNames = false; | 131 bool mustPreserveNames = false; |
| 35 | 132 |
| 36 /// True if a call to disableTreeShaking has been seen. | 133 /// True if a call to disableTreeShaking has been seen. |
| 37 bool isTreeShakingDisabled = false; | 134 bool isTreeShakingDisabled = false; |
| 38 | 135 |
| 39 /// True if there isn't sufficient @MirrorsUsed data. | 136 /// True if there isn't sufficient @MirrorsUsed data. |
| 40 bool hasInsufficientMirrorsUsed = false; | 137 bool hasInsufficientMirrorsUsed = false; |
| 41 | 138 |
| 42 /// True if a call to preserveUris has been seen and the preserve-uris flag | 139 /// True if a call to preserveUris has been seen and the preserve-uris flag |
| 43 /// is set. | 140 /// is set. |
| 44 bool mustPreserveUris = false; | 141 bool mustPreserveUris = false; |
| 45 | 142 |
| 46 /// List of symbols that the user has requested for reflection. | 143 /// Set of symbols that the user has requested for reflection. |
| 47 final Set<String> symbolsUsed = new Set<String>(); | 144 final Set<String> symbolsUsed = new Set<String>(); |
| 48 | 145 |
| 49 /// List of elements that the user has requested for reflection. | 146 /// Set of elements that the user has requested for reflection. |
| 50 final Set<Element> targetsUsed = new Set<Element>(); | 147 final Set<Element> targetsUsed = new Set<Element>(); |
| 51 | 148 |
| 52 /// List of annotations provided by user that indicate that the annotated | 149 /// List of annotations provided by user that indicate that the annotated |
| 53 /// element must be retained. | 150 /// element must be retained. |
| 54 final Set<Element> metaTargetsUsed = new Set<Element>(); | 151 final Set<Element> metaTargetsUsed = new Set<Element>(); |
| 55 | 152 |
| 56 // TODO(johnniwinther): Avoid the need for this. | 153 // TODO(johnniwinther): Avoid the need for this. |
| 57 final Compiler _compiler; | 154 final Compiler _compiler; |
| 58 | 155 |
| 59 final CompilerOptions _options; | 156 final CompilerOptions _options; |
| 60 | 157 |
| 61 final CommonElements _commonElements; | 158 final CommonElements _commonElements; |
| 62 | 159 |
| 63 final BackendHelpers _helpers; | 160 final BackendHelpers _helpers; |
| 64 | 161 |
| 65 final JavaScriptConstantCompiler _constants; | 162 final JavaScriptConstantCompiler _constants; |
| 66 | 163 |
| 67 MirrorsData(this._compiler, this._options, this._commonElements, | 164 MirrorsDataImpl(this._compiler, this._options, this._commonElements, |
| 68 this._helpers, this._constants); | 165 this._helpers, this._constants); |
| 69 | 166 |
| 70 void registerUsedMember(MemberElement member) { | 167 void registerUsedMember(MemberElement member) { |
| 71 if (member == _helpers.disableTreeShakingMarker) { | 168 if (member == _helpers.disableTreeShakingMarker) { |
| 72 isTreeShakingDisabled = true; | 169 isTreeShakingDisabled = true; |
| 73 } else if (member == _helpers.preserveNamesMarker) { | 170 } else if (member == _helpers.preserveNamesMarker) { |
| 74 mustPreserveNames = true; | 171 mustPreserveNames = true; |
| 75 } else if (member == _helpers.preserveMetadataMarker) { | 172 } else if (member == _helpers.preserveMetadataMarker) { |
| 76 mustRetainMetadata = true; | 173 mustRetainMetadata = true; |
| 77 } else if (member == _helpers.preserveUrisMarker) { | 174 } else if (member == _helpers.preserveUrisMarker) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 targetsUsed.add(field.getter); | 254 targetsUsed.add(field.getter); |
| 158 targetsUsed.add(field.setter); | 255 targetsUsed.add(field.setter); |
| 159 } else { | 256 } else { |
| 160 targetsUsed.add(target); | 257 targetsUsed.add(target); |
| 161 } | 258 } |
| 162 } | 259 } |
| 163 } | 260 } |
| 164 if (metaTargets != null) metaTargetsUsed.addAll(metaTargets); | 261 if (metaTargets != null) metaTargetsUsed.addAll(metaTargets); |
| 165 } | 262 } |
| 166 | 263 |
| 167 /** | 264 /// Returns `true` if [element] can be accessed through reflection, that is, |
| 168 * Returns `true` if [element] can be accessed through reflection, that is, | 265 /// is in the set of elements covered by a `MirrorsUsed` annotation. |
| 169 * is in the set of elements covered by a `MirrorsUsed` annotation. | 266 /// |
| 170 * | 267 /// This property is used to tag emitted elements with a marker which is |
| 171 * This property is used to tag emitted elements with a marker which is | 268 /// checked by the runtime system to throw an exception if an element is |
| 172 * checked by the runtime system to throw an exception if an element is | 269 /// accessed (invoked, get, set) that is not accessible for the reflective |
| 173 * accessed (invoked, get, set) that is not accessible for the reflective | 270 /// system. |
| 174 * system. | |
| 175 */ | |
| 176 bool isAccessibleByReflection(Element element) { | 271 bool isAccessibleByReflection(Element element) { |
| 177 if (element.isClass) { | 272 if (element.isClass) { |
| 178 element = _getDartClass(element); | 273 element = _getDartClass(element); |
| 179 } | 274 } |
| 180 return membersNeededForReflection.contains(element); | 275 return membersNeededForReflection.contains(element); |
| 181 } | 276 } |
| 182 | 277 |
| 183 ClassElement _getDartClass(ClassElement cls) { | 278 ClassElement _getDartClass(ClassElement cls) { |
| 184 if (cls == _helpers.jsIntClass) { | 279 if (cls == _helpers.jsIntClass) { |
| 185 return _commonElements.intClass; | 280 return _commonElements.intClass; |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 // [computeMembersNeededForReflection]. | 498 // [computeMembersNeededForReflection]. |
| 404 void maybeMarkClosureAsNeededForReflection( | 499 void maybeMarkClosureAsNeededForReflection( |
| 405 ClosureClassElement globalizedElement, | 500 ClosureClassElement globalizedElement, |
| 406 FunctionElement callFunction, | 501 FunctionElement callFunction, |
| 407 FunctionElement function) { | 502 FunctionElement function) { |
| 408 if (!_membersNeededForReflection.contains(function)) return; | 503 if (!_membersNeededForReflection.contains(function)) return; |
| 409 _membersNeededForReflection.add(callFunction); | 504 _membersNeededForReflection.add(callFunction); |
| 410 _membersNeededForReflection.add(globalizedElement); | 505 _membersNeededForReflection.add(globalizedElement); |
| 411 } | 506 } |
| 412 | 507 |
| 413 /// Called when [:const Symbol(name):] is seen. | 508 /// Called when `const Symbol(name)` is seen. |
| 414 void registerConstSymbol(String name) { | 509 void registerConstSymbol(String name) { |
| 415 symbolsUsed.add(name); | 510 symbolsUsed.add(name); |
| 416 if (name.endsWith('=')) { | 511 if (name.endsWith('=')) { |
| 417 symbolsUsed.add(name.substring(0, name.length - 1)); | 512 symbolsUsed.add(name.substring(0, name.length - 1)); |
| 418 } | 513 } |
| 419 } | 514 } |
| 420 } | 515 } |
| OLD | NEW |