Index: pkg/compiler/lib/src/js_backend/backend.dart |
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart |
index e04aa6c8a991b49aea15f26be89224a53ecfd80c..dde14af3a638d0a6975399aac9c7507b317c050b 100644 |
--- a/pkg/compiler/lib/src/js_backend/backend.dart |
+++ b/pkg/compiler/lib/src/js_backend/backend.dart |
@@ -449,6 +449,9 @@ class JavaScriptBackend extends Backend { |
/// these constants must be registered. |
final List<Dependency> metadataConstants = <Dependency>[]; |
+ /// Set of elements for which metadata has been registered as dependencies. |
+ final Set<Element> _registeredMetadata = new Set<Element>(); |
+ |
/// List of elements that the user has requested for reflection. |
final Set<Element> targetsUsed = new Set<Element>(); |
@@ -1047,21 +1050,12 @@ class JavaScriptBackend extends Backend { |
// helper so we register a use of that. |
registry.registerStaticUse(new StaticUse.staticInvoke( |
// TODO(johnniwinther): Find the right [CallStructure]. |
- |
helpers.createRuntimeType, |
null)); |
} |
} |
} |
- void registerMetadataConstant(MetadataAnnotation metadata, |
- Element annotatedElement, Registry registry) { |
- assert(registry.isForResolution); |
- ConstantValue constant = constants.getConstantValueForMetadata(metadata); |
- registerCompileTimeConstant(constant, registry); |
- metadataConstants.add(new Dependency(constant, annotatedElement)); |
- } |
- |
void registerInstantiatedClass( |
ClassElement cls, Enqueuer enqueuer, Registry registry) { |
_processClass(cls, enqueuer, registry); |
@@ -1272,6 +1266,7 @@ class JavaScriptBackend extends Backend { |
super.onResolutionComplete(); |
computeMembersNeededForReflection(); |
rti.computeClassesNeedingRti(); |
+ _registeredMetadata.clear(); |
} |
onTypeInferenceComplete() { |
@@ -2304,17 +2299,67 @@ class JavaScriptBackend extends Backend { |
reporter.log('Retaining metadata.'); |
compiler.libraryLoader.libraries.forEach(retainMetadataOf); |
- for (Dependency dependency in metadataConstants) { |
- registerCompileTimeConstant(dependency.constant, |
- new EagerRegistry('EagerRegistry for ${dependency}', enqueuer)); |
- } |
- if (!enqueuer.isResolutionQueue) { |
+ |
+ if (enqueuer.isResolutionQueue && !enqueuer.queueIsClosed) { |
+ /// Register the constant value of [metadata] as live in resolution. |
+ void registerMetadataConstant(MetadataAnnotation metadata) { |
+ ConstantValue constant = |
+ constants.getConstantValueForMetadata(metadata); |
+ Dependency dependency = |
+ new Dependency(constant, metadata.annotatedElement); |
+ metadataConstants.add(dependency); |
+ registerCompileTimeConstant(dependency.constant, |
+ new EagerRegistry('EagerRegistry for ${dependency}', enqueuer)); |
+ } |
+ |
+ // TODO(johnniwinther): We should have access to all recently processed |
+ // elements and process these instead. |
+ processMetadata(compiler.enqueuer.resolution.processedElements, |
+ registerMetadataConstant); |
+ } else { |
+ for (Dependency dependency in metadataConstants) { |
+ registerCompileTimeConstant(dependency.constant, |
+ new EagerRegistry('EagerRegistry for ${dependency}', enqueuer)); |
+ } |
metadataConstants.clear(); |
} |
} |
return true; |
} |
+ /// Call [registerMetadataConstant] on all metadata from [elements]. |
+ void processMetadata(Iterable<Element> elements, |
+ void onMetadata(MetadataAnnotation metadata)) { |
+ void processLibraryMetadata(LibraryElement library) { |
+ if (_registeredMetadata.add(library)) { |
+ library.metadata.forEach(onMetadata); |
+ library.entryCompilationUnit.metadata.forEach(onMetadata); |
+ for (ImportElement import in library.imports) { |
+ import.metadata.forEach(onMetadata); |
+ } |
+ } |
+ } |
+ |
+ void processElementMetadata(Element element) { |
+ if (_registeredMetadata.add(element)) { |
+ element.metadata.forEach(onMetadata); |
+ if (element.isFunction) { |
+ FunctionElement function = element; |
+ for (ParameterElement parameter in function.parameters) { |
+ parameter.metadata.forEach(onMetadata); |
+ } |
+ } |
+ if (element.enclosingClass != null) { |
+ processElementMetadata(element.enclosingClass); |
+ } else { |
+ processLibraryMetadata(element.library); |
+ } |
+ } |
+ } |
+ |
+ elements.forEach(processElementMetadata); |
+ } |
+ |
void onQueueClosed() { |
lookupMapAnalysis.onQueueClosed(); |
jsInteropAnalysis.onQueueClosed(); |
@@ -3037,6 +3082,8 @@ class Dependency { |
final Element annotatedElement; |
const Dependency(this.constant, this.annotatedElement); |
+ |
+ String toString() => '$annotatedElement:${constant.toStructuredText()}'; |
} |
class JavaScriptImpactStrategy extends ImpactStrategy { |