| Index: pkg/compiler/lib/src/js_backend/mirrors_data.dart
|
| diff --git a/pkg/compiler/lib/src/js_backend/mirrors_data.dart b/pkg/compiler/lib/src/js_backend/mirrors_data.dart
|
| index 413b5dde507a31a1c43f177bcd129573b2d5f555..a946faf39df1b2acea32fc5013a9ae0b52135ac2 100644
|
| --- a/pkg/compiler/lib/src/js_backend/mirrors_data.dart
|
| +++ b/pkg/compiler/lib/src/js_backend/mirrors_data.dart
|
| @@ -15,7 +15,6 @@ import '../options.dart';
|
| import '../world.dart';
|
| import '../universe/world_builder.dart';
|
| import '../util/emptyset.dart';
|
| -import 'constant_handler_javascript.dart';
|
|
|
| abstract class MirrorsData {
|
| /// True if a call to preserveMetadataMarker has been seen. This means that
|
| @@ -78,7 +77,7 @@ abstract class MirrorsData {
|
| /// reflection is used in the program (and thus [isTreeShakingDisabled] is
|
| /// still false). Therefore _do not_ use this predicate to decide inclusion
|
| /// in the tree, use [requiredByMirrorSystem] instead.
|
| - bool isClassReferencedFromMirrorSystem(covariant ClassEntity element);
|
| + bool isClassReferencedFromMirrorSystem(ClassEntity element);
|
|
|
| /// Returns `true` if the member [element] is covered by a `MirrorsUsed`
|
| /// annotation.
|
| @@ -87,11 +86,11 @@ abstract class MirrorsData {
|
| /// reflection is used in the program (and thus [isTreeShakingDisabled] is
|
| /// still false). Therefore _do not_ use this predicate to decide inclusion
|
| /// in the tree, use [requiredByMirrorSystem] instead.
|
| - bool isMemberReferencedFromMirrorSystem(covariant MemberEntity element);
|
| + bool isMemberReferencedFromMirrorSystem(MemberEntity element);
|
|
|
| /// Returns `true` if the library [element] is covered by a `MirrorsUsed`
|
| /// annotation.
|
| - bool isLibraryReferencedFromMirrorSystem(covariant LibraryEntity element);
|
| + bool isLibraryReferencedFromMirrorSystem(LibraryEntity element);
|
|
|
| /// Returns `true` if the typedef [element] needs reflection information at
|
| /// runtime.
|
| @@ -100,7 +99,7 @@ abstract class MirrorsData {
|
| /// checked by the runtime system to throw an exception if an element is
|
| /// accessed (invoked, get, set) that is not accessible for the reflective
|
| /// system.
|
| - bool isTypedefAccessibleByReflection(covariant TypedefEntity element);
|
| + bool isTypedefAccessibleByReflection(TypedefEntity element);
|
|
|
| /// Returns `true` if the class [element] needs reflection information at
|
| /// runtime.
|
| @@ -120,25 +119,22 @@ abstract class MirrorsData {
|
| /// system.
|
| bool isMemberAccessibleByReflection(MemberEntity element);
|
|
|
| - // TODO(johnniwinther): Remove this.
|
| - @deprecated
|
| - bool isAccessibleByReflection(Element element);
|
| -
|
| - bool retainMetadataOfLibrary(covariant LibraryEntity element,
|
| + bool retainMetadataOfLibrary(LibraryEntity element,
|
| {bool addForEmission: true});
|
| - bool retainMetadataOfTypedef(covariant TypedefEntity element);
|
| - bool retainMetadataOfClass(covariant ClassEntity element);
|
| - bool retainMetadataOfMember(covariant MemberEntity element);
|
| - bool retainMetadataOfParameter(ParameterElement element);
|
| + bool retainMetadataOfTypedef(TypedefEntity element);
|
| + bool retainMetadataOfClass(ClassEntity element);
|
| + bool retainMetadataOfMember(MemberEntity element);
|
|
|
| /// Returns true if this element has to be enqueued due to
|
| /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if
|
| /// normal tree shaking is still active ([isTreeShakingDisabled] is false).
|
| - bool requiredByMirrorSystem(Element element);
|
| + bool isLibraryRequiredByMirrorSystem(LibraryEntity element);
|
| + bool isClassRequiredByMirrorSystem(ClassEntity element);
|
| + bool isMemberRequiredByMirrorSystem(MemberEntity element);
|
| }
|
|
|
| abstract class MirrorsDataBuilder {
|
| - void registerUsedMember(MemberElement member);
|
| + void registerUsedMember(MemberEntity member);
|
|
|
| /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed
|
| /// annotations. The arguments corresponds to the unions of the corresponding
|
| @@ -205,13 +201,13 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder {
|
|
|
| final CompilerOptions _options;
|
|
|
| + final ElementEnvironment _elementEnvironment;
|
| final CommonElements _commonElements;
|
|
|
| - MirrorsDataImpl(this._compiler, this._options, this._commonElements);
|
| -
|
| - JavaScriptConstantCompiler get _constants => _compiler.backend.constants;
|
| + MirrorsDataImpl(this._compiler, this._options, this._elementEnvironment,
|
| + this._commonElements);
|
|
|
| - void registerUsedMember(MemberElement member) {
|
| + void registerUsedMember(MemberEntity member) {
|
| if (member == _commonElements.disableTreeShakingMarker) {
|
| isTreeShakingDisabled = true;
|
| } else if (member == _commonElements.preserveNamesMarker) {
|
| @@ -241,23 +237,12 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder {
|
| }
|
|
|
| @override
|
| - bool retainMetadataOfParameter(ParameterElement element) {
|
| - if (mustRetainMetadata) {
|
| - hasRetainedMetadata = true;
|
| - if (isParameterReferencedFromMirrorSystem(element)) {
|
| - _retainMetadataOf(element);
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - @override
|
| - bool retainMetadataOfMember(MemberElement element) {
|
| + bool retainMetadataOfMember(covariant MemberElement element) {
|
| if (mustRetainMetadata) {
|
| hasRetainedMetadata = true;
|
| if (isMemberReferencedFromMirrorSystem(element)) {
|
| - _retainMetadataOf(element);
|
| + _addConstantsForEmission(
|
| + getMemberMetadata(element, includeParameterMetadata: true));
|
| return true;
|
| }
|
| }
|
| @@ -265,11 +250,11 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder {
|
| }
|
|
|
| @override
|
| - bool retainMetadataOfClass(ClassElement element) {
|
| + bool retainMetadataOfClass(ClassEntity element) {
|
| if (mustRetainMetadata) {
|
| hasRetainedMetadata = true;
|
| if (isClassReferencedFromMirrorSystem(element)) {
|
| - _retainMetadataOf(element);
|
| + _addConstantsForEmission(getClassMetadata(element));
|
| return true;
|
| }
|
| }
|
| @@ -277,11 +262,11 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder {
|
| }
|
|
|
| @override
|
| - bool retainMetadataOfTypedef(TypedefElement element) {
|
| + bool retainMetadataOfTypedef(TypedefEntity element) {
|
| if (mustRetainMetadata) {
|
| hasRetainedMetadata = true;
|
| - if (isTypedefReferencedFromMirrorSystem(element)) {
|
| - _retainMetadataOf(element);
|
| + if (_isTypedefReferencedFromMirrorSystem(element)) {
|
| + _addConstantsForEmission(getTypedefMetadata(element));
|
| return true;
|
| }
|
| }
|
| @@ -289,35 +274,52 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder {
|
| }
|
|
|
| @override
|
| - bool retainMetadataOfLibrary(LibraryElement element,
|
| + bool retainMetadataOfLibrary(LibraryEntity element,
|
| {bool addForEmission: true}) {
|
| if (mustRetainMetadata) {
|
| hasRetainedMetadata = true;
|
| if (isLibraryReferencedFromMirrorSystem(element)) {
|
| - _retainMetadataOf(element, addForEmission: addForEmission);
|
| + Iterable<ConstantValue> constants = getLibraryMetadata(element);
|
| + if (addForEmission) {
|
| + _addConstantsForEmission(constants);
|
| + }
|
| return true;
|
| }
|
| }
|
| return false;
|
| }
|
|
|
| - void _retainMetadataOf(Element element, {bool addForEmission: true}) {
|
| - for (MetadataAnnotation metadata in element.metadata) {
|
| - metadata.ensureResolved(_compiler.resolution);
|
| - ConstantValue constant = _constants.getConstantValueForMetadata(metadata);
|
| - if (addForEmission) {
|
| - CodegenWorldBuilder worldBuilder = _compiler.codegenWorldBuilder;
|
| - worldBuilder.addCompileTimeConstantForEmission(constant);
|
| - }
|
| + Iterable<ConstantValue> getLibraryMetadata(LibraryElement element) {
|
| + return _elementEnvironment.getLibraryMetadata(element);
|
| + }
|
| +
|
| + Iterable<ConstantValue> getClassMetadata(ClassElement element) {
|
| + return _elementEnvironment.getClassMetadata(element);
|
| + }
|
| +
|
| + Iterable<ConstantValue> getMemberMetadata(MemberEntity element,
|
| + {bool includeParameterMetadata}) {
|
| + return _elementEnvironment.getMemberMetadata(element,
|
| + includeParameterMetadata: includeParameterMetadata);
|
| + }
|
| +
|
| + Iterable<ConstantValue> getTypedefMetadata(TypedefElement element) {
|
| + return _elementEnvironment.getTypedefMetadata(element);
|
| + }
|
| +
|
| + void _addConstantsForEmission(Iterable<ConstantValue> constants) {
|
| + for (ConstantValue constant in constants) {
|
| + CodegenWorldBuilder worldBuilder = _compiler.codegenWorldBuilder;
|
| + worldBuilder.addCompileTimeConstantForEmission(constant);
|
| }
|
| }
|
|
|
| /// Sets of elements that are needed by reflection. Computed using
|
| /// [computeMembersNeededForReflection] on first use.
|
| - Set<ClassElement> _classesNeededForReflection;
|
| - Set<TypedefElement> _typedefsNeededForReflection;
|
| - Set<MemberElement> _membersNeededForReflection;
|
| - Set<LocalFunctionElement> _closuresNeededForReflection;
|
| + Set<ClassEntity> _classesNeededForReflection;
|
| + Set<TypedefEntity> _typedefsNeededForReflection;
|
| + Set<MemberEntity> _membersNeededForReflection;
|
| + Set<Local> _closuresNeededForReflection;
|
|
|
| /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed
|
| /// annotations. The arguments corresponds to the unions of the corresponding
|
| @@ -368,24 +370,10 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder {
|
| }
|
|
|
| @override
|
| - bool isTypedefAccessibleByReflection(TypedefElement element) {
|
| + bool isTypedefAccessibleByReflection(TypedefEntity element) {
|
| return _typedefsNeededForReflection.contains(element);
|
| }
|
|
|
| - bool isAccessibleByReflection(Element element) {
|
| - if (element.isLibrary) {
|
| - return false;
|
| - } else if (element.isClass) {
|
| - ClassElement cls = element;
|
| - return isClassAccessibleByReflection(cls);
|
| - } else if (element.isTypedef) {
|
| - return isTypedefAccessibleByReflection(element);
|
| - } else {
|
| - MemberElement member = element;
|
| - return isMemberAccessibleByReflection(member);
|
| - }
|
| - }
|
| -
|
| ClassEntity _getDartClass(ClassEntity cls) {
|
| if (cls == _commonElements.jsIntClass) {
|
| return _commonElements.intClass;
|
| @@ -413,22 +401,31 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder {
|
| /// Returns true if this element has to be enqueued due to
|
| /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if
|
| /// normal tree shaking is still active ([isTreeShakingDisabled] is false).
|
| - bool requiredByMirrorSystem(Element element) {
|
| + bool isLibraryRequiredByMirrorSystem(LibraryEntity element) {
|
| return hasInsufficientMirrorsUsed && isTreeShakingDisabled ||
|
| - matchesMirrorsMetaTarget(element) ||
|
| - classesInMirrorsUsedTargets.contains(element) ||
|
| - membersInMirrorsUsedTargets.contains(element) ||
|
| - librariesInMirrorsUsedTargets.contains(element) ||
|
| - _typedefsInMirrorsUsedTargets.contains(element);
|
| + _libraryMatchesMirrorsMetaTarget(element) ||
|
| + librariesInMirrorsUsedTargets.contains(element);
|
| + }
|
| +
|
| + bool isClassRequiredByMirrorSystem(ClassEntity element) {
|
| + return hasInsufficientMirrorsUsed && isTreeShakingDisabled ||
|
| + _classMatchesMirrorsMetaTarget(element) ||
|
| + classesInMirrorsUsedTargets.contains(element);
|
| + }
|
| +
|
| + bool isMemberRequiredByMirrorSystem(MemberEntity element) {
|
| + return hasInsufficientMirrorsUsed && isTreeShakingDisabled ||
|
| + _memberMatchesMirrorsMetaTarget(element) ||
|
| + membersInMirrorsUsedTargets.contains(element);
|
| }
|
|
|
| @override
|
| - bool isLibraryReferencedFromMirrorSystem(LibraryElement element) {
|
| + bool isLibraryReferencedFromMirrorSystem(LibraryEntity element) {
|
| return _libraryReferencedFromMirrorSystem(element);
|
| }
|
|
|
| @override
|
| - bool isMemberReferencedFromMirrorSystem(MemberElement element) {
|
| + bool isMemberReferencedFromMirrorSystem(MemberEntity element) {
|
| if (_memberReferencedFromMirrorSystem(element)) return true;
|
| if (element.enclosingClass != null) {
|
| return isClassReferencedFromMirrorSystem(element.enclosingClass);
|
| @@ -438,64 +435,69 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder {
|
| }
|
|
|
| @override
|
| - bool isClassReferencedFromMirrorSystem(ClassElement element) {
|
| + bool isClassReferencedFromMirrorSystem(ClassEntity element) {
|
| return _classReferencedFromMirrorSystem(element) ||
|
| isLibraryReferencedFromMirrorSystem(element.library);
|
| }
|
|
|
| - bool isParameterReferencedFromMirrorSystem(ParameterElement element) {
|
| - return _parameterReferencedFromMirrorSystem(element) ||
|
| - isMemberReferencedFromMirrorSystem(element.memberContext);
|
| - }
|
| -
|
| - bool isTypedefReferencedFromMirrorSystem(TypedefElement element) {
|
| + bool _isTypedefReferencedFromMirrorSystem(TypedefEntity element) {
|
| return _typedefReferencedFromMirrorSystem(element) ||
|
| isLibraryReferencedFromMirrorSystem(element.library);
|
| }
|
|
|
| - bool _memberReferencedFromMirrorSystem(MemberElement element) {
|
| + bool _memberReferencedFromMirrorSystem(MemberEntity element) {
|
| return hasInsufficientMirrorsUsed ||
|
| - matchesMirrorsMetaTarget(element) ||
|
| + _memberMatchesMirrorsMetaTarget(element) ||
|
| membersInMirrorsUsedTargets.contains(element);
|
| }
|
|
|
| - bool _parameterReferencedFromMirrorSystem(ParameterElement element) {
|
| - return hasInsufficientMirrorsUsed || matchesMirrorsMetaTarget(element);
|
| - }
|
| -
|
| - bool _classReferencedFromMirrorSystem(ClassElement element) {
|
| + bool _classReferencedFromMirrorSystem(ClassEntity element) {
|
| return hasInsufficientMirrorsUsed ||
|
| - matchesMirrorsMetaTarget(element) ||
|
| + _classMatchesMirrorsMetaTarget(element) ||
|
| classesInMirrorsUsedTargets.contains(element);
|
| }
|
|
|
| - bool _typedefReferencedFromMirrorSystem(TypedefElement element) {
|
| + bool _typedefReferencedFromMirrorSystem(TypedefEntity element) {
|
| return hasInsufficientMirrorsUsed ||
|
| - matchesMirrorsMetaTarget(element) ||
|
| + _typedefMatchesMirrorsMetaTarget(element) ||
|
| _typedefsInMirrorsUsedTargets.contains(element);
|
| }
|
|
|
| - bool _libraryReferencedFromMirrorSystem(LibraryElement element) {
|
| + bool _libraryReferencedFromMirrorSystem(LibraryEntity element) {
|
| return hasInsufficientMirrorsUsed ||
|
| - matchesMirrorsMetaTarget(element) ||
|
| + _libraryMatchesMirrorsMetaTarget(element) ||
|
| librariesInMirrorsUsedTargets.contains(element);
|
| }
|
|
|
| + bool _libraryMatchesMirrorsMetaTarget(LibraryElement element) {
|
| + if (metaTargetsUsed.isEmpty) return false;
|
| + return _matchesMirrorsMetaTarget(getLibraryMetadata(element));
|
| + }
|
| +
|
| + bool _classMatchesMirrorsMetaTarget(ClassEntity element) {
|
| + if (metaTargetsUsed.isEmpty) return false;
|
| + return _matchesMirrorsMetaTarget(getClassMetadata(element));
|
| + }
|
| +
|
| + bool _memberMatchesMirrorsMetaTarget(MemberElement element) {
|
| + if (metaTargetsUsed.isEmpty) return false;
|
| + return _matchesMirrorsMetaTarget(
|
| + getMemberMetadata(element, includeParameterMetadata: false));
|
| + }
|
| +
|
| + bool _typedefMatchesMirrorsMetaTarget(TypedefElement element) {
|
| + if (metaTargetsUsed.isEmpty) return false;
|
| + return _matchesMirrorsMetaTarget(getTypedefMetadata(element));
|
| + }
|
| +
|
| /**
|
| * Returns `true` if the element is needed because it has an annotation
|
| * of a type that is used as a meta target for reflection.
|
| */
|
| - bool matchesMirrorsMetaTarget(Element element) {
|
| + bool _matchesMirrorsMetaTarget(Iterable<ConstantValue> constants) {
|
| if (metaTargetsUsed.isEmpty) return false;
|
| - for (MetadataAnnotation metadata in element.metadata) {
|
| - // TODO(kasperl): It would be nice if we didn't have to resolve
|
| - // all metadata but only stuff that potentially would match one
|
| - // of the used meta targets.
|
| - metadata.ensureResolved(_compiler.resolution);
|
| - ConstantValue value =
|
| - _compiler.constants.getConstantValue(metadata.constant);
|
| - if (value == null) continue;
|
| - DartType type = value.getType(_commonElements);
|
| + for (ConstantValue constant in constants) {
|
| + DartType type = constant.getType(_commonElements);
|
| if (type is InterfaceType && metaTargetsUsed.contains(type.element))
|
| return true;
|
| }
|
| @@ -529,17 +531,19 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder {
|
| createImmutableSets();
|
| return;
|
| }
|
| - _classesNeededForReflection = new Set<ClassElement>();
|
| - _typedefsNeededForReflection = new Set<TypedefElement>();
|
| - _membersNeededForReflection = new Set<MemberElement>();
|
| - _closuresNeededForReflection = new Set<LocalFunctionElement>();
|
| + _classesNeededForReflection = new Set<ClassEntity>();
|
| + _typedefsNeededForReflection = new Set<TypedefEntity>();
|
| + _membersNeededForReflection = new Set<MemberEntity>();
|
| + _closuresNeededForReflection = new Set<Local>();
|
|
|
| // Compute a mapping from class to the closures it contains, so we
|
| // can include the correct ones when including the class.
|
| - Map<ClassElement, List<LocalFunctionElement>> closureMap =
|
| - new Map<ClassElement, List<LocalFunctionElement>>();
|
| - for (LocalFunctionElement closure in worldBuilder.localFunctions) {
|
| - closureMap.putIfAbsent(closure.enclosingClass, () => []).add(closure);
|
| + Map<ClassEntity, List<Local>> closureMap =
|
| + new Map<ClassEntity, List<Local>>();
|
| + for (Local closure in worldBuilder.localFunctions) {
|
| + closureMap
|
| + .putIfAbsent(closure.memberContext.enclosingClass, () => [])
|
| + .add(closure);
|
| }
|
| bool foundClosure = false;
|
| for (ClassElement cls in worldBuilder.directlyInstantiatedClasses) {
|
| @@ -587,7 +591,7 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder {
|
| });
|
| }
|
| // 5) all its closures
|
| - List<LocalFunctionElement> closures = closureMap[cls];
|
| + List<Local> closures = closureMap[cls];
|
| if (closures != null) {
|
| _closuresNeededForReflection.addAll(closures);
|
| foundClosure = true;
|
| @@ -609,10 +613,10 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder {
|
| });
|
| // Also add in closures. Those might be reflectable is their enclosing
|
| // member is.
|
| - List<LocalFunctionElement> closures = closureMap[cls];
|
| + List<Local> closures = closureMap[cls];
|
| if (closures != null) {
|
| - for (LocalFunctionElement closure in closures) {
|
| - MemberElement member = closure.memberContext;
|
| + for (Local closure in closures) {
|
| + MemberEntity member = closure.memberContext;
|
| if (_memberReferencedFromMirrorSystem(member)) {
|
| _closuresNeededForReflection.add(closure);
|
| foundClosure = true;
|
| @@ -638,7 +642,7 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder {
|
| // And closures inside top-level elements that do not have a surrounding
|
| // class. These will be in the [:null:] bucket of the [closureMap].
|
| if (closureMap.containsKey(null)) {
|
| - for (LocalFunctionElement closure in closureMap[null]) {
|
| + for (Local closure in closureMap[null]) {
|
| if (isMemberReferencedFromMirrorSystem(closure.memberContext)) {
|
| _closuresNeededForReflection.add(closure);
|
| foundClosure = true;
|
| @@ -648,31 +652,31 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder {
|
| // As we do not think about closures as classes, yet, we have to make sure
|
| // their superclasses are available for reflection manually.
|
| if (foundClosure) {
|
| - ClassElement cls = _commonElements.closureClass;
|
| + ClassEntity cls = _commonElements.closureClass;
|
| _classesNeededForReflection.add(cls);
|
| }
|
| Set<FunctionEntity> closurizedMembers = worldBuilder.closurizedMembers;
|
| if (closurizedMembers.any(_membersNeededForReflection.contains)) {
|
| - ClassElement cls = _commonElements.boundClosureClass;
|
| + ClassEntity cls = _commonElements.boundClosureClass;
|
| _classesNeededForReflection.add(cls);
|
| }
|
| // Add typedefs.
|
| - for (TypedefElement element in closedWorld.allTypedefs) {
|
| - if (isTypedefReferencedFromMirrorSystem(element)) {
|
| + for (TypedefEntity element in closedWorld.allTypedefs) {
|
| + if (_isTypedefReferencedFromMirrorSystem(element)) {
|
| _typedefsNeededForReflection.add(element);
|
| }
|
| }
|
| // Register all symbols of reflectable elements
|
| - for (ClassElement element in _classesNeededForReflection) {
|
| + for (ClassEntity element in _classesNeededForReflection) {
|
| symbolsUsed.add(element.name);
|
| }
|
| - for (TypedefElement element in _typedefsNeededForReflection) {
|
| + for (TypedefEntity element in _typedefsNeededForReflection) {
|
| symbolsUsed.add(element.name);
|
| }
|
| - for (MemberElement element in _membersNeededForReflection) {
|
| + for (MemberEntity element in _membersNeededForReflection) {
|
| symbolsUsed.add(element.name);
|
| }
|
| - for (LocalFunctionElement element in _closuresNeededForReflection) {
|
| + for (Local element in _closuresNeededForReflection) {
|
| symbolsUsed.add(element.name);
|
| }
|
| }
|
|
|