From 368d4d54d3634cfbbbfcf63bce8d024dd7b9a4ae Mon Sep 17 00:00:00 2001 From: Johnni Winther Date: Thu, 16 Jun 2016 10:11:51 +0200 Subject: [PATCH] Revert "Remove Registry from registerMetadataConstant" and "Serialize metadata" This reverts commit ed1777e4b26643099ef0c24cd53d5c1629850141. This reverts commit f8e3f223476b461d4c9fcf89b691441f73532bf4. Review URL: https://codereview.chromium.org/2070493003 . --- pkg/compiler/lib/src/common/backend_api.dart | 33 ++++----- .../lib/src/compile_time_constants.dart | 27 +------- pkg/compiler/lib/src/compiler.dart | 8 +-- pkg/compiler/lib/src/constants/values.dart | 3 +- .../lib/src/cps_ir/cps_ir_nodes_sexpr.dart | 4 -- pkg/compiler/lib/src/elements/elements.dart | 4 +- pkg/compiler/lib/src/elements/modelx.dart | 7 -- pkg/compiler/lib/src/enqueue.dart | 1 - pkg/compiler/lib/src/js_backend/backend.dart | 67 ++++--------------- .../lib/src/js_backend/constant_emitter.dart | 5 -- .../constant_handler_javascript.dart | 38 ++++++++++- .../src/js_backend/js_interop_analysis.dart | 3 - pkg/compiler/lib/src/js_backend/namer.dart | 8 --- .../lib/src/js_emitter/constant_ordering.dart | 6 -- pkg/compiler/lib/src/native/enqueue.dart | 4 +- .../lib/src/parser/element_listener.dart | 5 +- pkg/compiler/lib/src/patch_parser.dart | 7 +- pkg/compiler/lib/src/resolution/registry.dart | 4 ++ .../lib/src/resolution/resolution.dart | 1 + .../serialization/element_serialization.dart | 33 --------- .../lib/src/serialization/equivalence.dart | 9 --- pkg/compiler/lib/src/serialization/keys.dart | 2 - .../lib/src/serialization/modelz.dart | 51 +------------- pkg/compiler/lib/src/types/constants.dart | 5 -- tests/compiler/dart2js/mirrors_used_test.dart | 18 ++--- .../serialization/equivalence_test.dart | 22 ------ .../dart2js/serialization/model_test.dart | 7 +- .../dart2js/serialization/test_helper.dart | 4 +- 28 files changed, 106 insertions(+), 280 deletions(-) diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart index c4c9020931b..5bbb2f0655f 100644 --- a/pkg/compiler/lib/src/common/backend_api.dart +++ b/pkg/compiler/lib/src/common/backend_api.dart @@ -131,6 +131,11 @@ abstract class Backend extends Target { /// Called during codegen when [constant] has been used. void registerCompileTimeConstant(ConstantValue constant, Registry registry) {} + /// Called during resolution when a constant value for [metadata] on + /// [annotatedElement] has been evaluated. + void registerMetadataConstant(MetadataAnnotation metadata, + Element annotatedElement, Registry registry) {} + /// Called to notify to the backend that a class is being instantiated. // TODO(johnniwinther): Remove this. It's only called once for each [cls] and // only with [Compiler.globalDependencies] as [registry]. @@ -273,25 +278,23 @@ abstract class Backend extends Target { /// been scanned. Future onLibraryScanned(LibraryElement library, LibraryLoader loader) { // TODO(johnniwinther): Move this to [JavaScriptBackend]. - if (!compiler.serialization.isDeserialized(library)) { - if (canLibraryUseNative(library)) { - library.forEachLocalMember((Element element) { - if (element.isClass) { - checkNativeAnnotation(compiler, element); - } - }); - } - checkJsInteropAnnotation(compiler, library); + if (canLibraryUseNative(library)) { library.forEachLocalMember((Element element) { - checkJsInteropAnnotation(compiler, element); - if (element.isClass && isJsInterop(element)) { - ClassElement classElement = element; - classElement.forEachMember((_, memberElement) { - checkJsInteropAnnotation(compiler, memberElement); - }); + if (element.isClass) { + checkNativeAnnotation(compiler, element); } }); } + checkJsInteropAnnotation(compiler, library); + library.forEachLocalMember((Element element) { + checkJsInteropAnnotation(compiler, element); + if (element.isClass && isJsInterop(element)) { + ClassElement classElement = element; + classElement.forEachMember((_, memberElement) { + checkJsInteropAnnotation(compiler, memberElement); + }); + } + }); return new Future.value(); } diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart index 71962e88957..bbabcf9f9aa 100644 --- a/pkg/compiler/lib/src/compile_time_constants.dart +++ b/pkg/compiler/lib/src/compile_time_constants.dart @@ -165,9 +165,7 @@ abstract class ConstantCompilerBase implements ConstantCompiler { @override @deprecated ConstantValue getConstantValueForVariable(VariableElement element) { - ConstantExpression constant = initialVariableValues[element.declaration]; - // TODO(johnniwinther): Support eager evaluation of the constant. - return constant != null ? getConstantValue(constant) : null; + return getConstantValue(initialVariableValues[element.declaration]); } ConstantExpression compileConstant(VariableElement element) { @@ -322,27 +320,8 @@ abstract class ConstantCompilerBase implements ConstantCompiler { return constantValueMap.containsKey(expression); } - @override ConstantValue getConstantValue(ConstantExpression expression) { - assert(invariant(CURRENT_ELEMENT_SPANNABLE, expression != null, - message: "ConstantExpression is null in getConstantValue.")); - // TODO(johnniwinther): ensure expressions have been evaluated at this - // point. This can't be enabled today due to dartbug.com/26406. - if (compiler.serialization.supportsDeserialization) { - evaluate(expression); - } - ConstantValue value = constantValueMap[expression]; - if (value == null && - expression != null && - expression.kind == ConstantExpressionKind.ERRONEOUS) { - // TODO(johnniwinther): When the Dart constant system sees a constant - // expression as erroneous but the JavaScript constant system finds it ok - // we have store a constant value for the erroneous constant expression. - // Ensure the computed constant expressions are always the same; that only - // the constant values may be different. - value = new NullConstantValue(); - } - return value; + return constantValueMap[expression]; } ConstantExpression compileNode(Node node, TreeElements elements, @@ -380,7 +359,7 @@ class DartConstantCompiler extends ConstantCompilerBase { Node node, TreeElements definitions, {bool isConst: true}) { ConstantExpression constant = definitions.getConstant(node); - if (constant != null && hasConstantValue(constant)) { + if (constant != null && getConstantValue(constant) != null) { return constant; } constant = diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart index 94b573a422d..234c7e17f18 100644 --- a/pkg/compiler/lib/src/compiler.dart +++ b/pkg/compiler/lib/src/compiler.dart @@ -1658,9 +1658,8 @@ class CompilerDiagnosticReporter extends DiagnosticReporter { if (astElement.hasNode) { Token from = astElement.node.getBeginToken(); Token to = astElement.node.getEndToken(); - if (astElement.metadata.isNotEmpty && - astElement.metadata.first.hasNode) { - from = astElement.metadata.first.node.getBeginToken(); + if (astElement.metadata.isNotEmpty) { + from = astElement.metadata.first.beginToken; } return validateToken(from, to); } @@ -1741,7 +1740,8 @@ class CompilerDiagnosticReporter extends DiagnosticReporter { } else if (node is Element) { return spanFromElement(node); } else if (node is MetadataAnnotation) { - return node.sourcePosition; + Uri uri = node.annotatedElement.compilationUnit.script.resourceUri; + return spanFromTokens(node.beginToken, node.endToken, uri); } else if (node is Local) { Local local = node; return spanFromElement(local.executableContext); diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart index 670d1efde88..37f5646d7e3 100644 --- a/pkg/compiler/lib/src/constants/values.dart +++ b/pkg/compiler/lib/src/constants/values.dart @@ -28,7 +28,6 @@ abstract class ConstantValueVisitor { R visitInterceptor(InterceptorConstantValue constant, A arg); R visitSynthetic(SyntheticConstantValue constant, A arg); R visitDeferred(DeferredConstantValue constant, A arg); - R visitNonConstant(NonConstantValue constant, A arg); } abstract class ConstantValue { @@ -763,7 +762,7 @@ class NonConstantValue extends ConstantValue { @override accept(ConstantValueVisitor visitor, arg) { - return visitor.visitNonConstant(this, arg); + // TODO(johnniwinther): Should this be part of the visiting? } @override diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart index d788549e624..1402b1d87b4 100644 --- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart @@ -475,10 +475,6 @@ class ConstantStringifier extends ConstantValueVisitor { return '(Null)'; } - String visitNonConstant(NonConstantValue constant, _) { - return '(NonConstant)'; - } - String visitInt(IntConstantValue constant, _) { return '(Int ${constant.toDartText()})'; } diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart index 06e0d002bab..e5338de2dec 100644 --- a/pkg/compiler/lib/src/elements/elements.dart +++ b/pkg/compiler/lib/src/elements/elements.dart @@ -1620,7 +1620,9 @@ abstract class MetadataAnnotation implements Spannable { /// The front-end constant of this metadata annotation. ConstantExpression get constant; Element get annotatedElement; - SourceSpan get sourcePosition; + int get resolutionState; + Token get beginToken; + Token get endToken; bool get hasNode; Node get node; diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart index 248a9ef9660..e1fd2710231 100644 --- a/pkg/compiler/lib/src/elements/modelx.dart +++ b/pkg/compiler/lib/src/elements/modelx.dart @@ -3193,8 +3193,6 @@ abstract class MetadataAnnotationX implements MetadataAnnotation { */ Token get beginToken; - Token get endToken; - MetadataAnnotationX([this.resolutionState = STATE_NOT_STARTED]); MetadataAnnotation ensureResolved(Resolution resolution) { @@ -3210,11 +3208,6 @@ abstract class MetadataAnnotationX implements MetadataAnnotation { Node parseNode(ParsingContext parsing); - SourceSpan get sourcePosition { - Uri uri = annotatedElement.compilationUnit.script.resourceUri; - return new SourceSpan.fromTokens(uri, beginToken, endToken); - } - String toString() => 'MetadataAnnotation($constant, $resolutionState)'; } diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart index a2690127a11..bcaec4a326a 100644 --- a/pkg/compiler/lib/src/enqueue.dart +++ b/pkg/compiler/lib/src/enqueue.dart @@ -449,7 +449,6 @@ abstract class Enqueuer { bool includeLibrary = shouldIncludeElementDueToMirrors(lib, includedEnclosing: false); lib.forEachLocalMember((Element member) { - if (member.isInjected) return; if (member.isClass) { enqueueReflectiveElementsInClass(member, recents, includeLibrary); } else { diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart index 40c11cac147..e04aa6c8a99 100644 --- a/pkg/compiler/lib/src/js_backend/backend.dart +++ b/pkg/compiler/lib/src/js_backend/backend.dart @@ -449,9 +449,6 @@ class JavaScriptBackend extends Backend { /// these constants must be registered. final List metadataConstants = []; - /// Set of elements for which metadata has been registered as dependencies. - final Set _registeredMetadata = new Set(); - /// List of elements that the user has requested for reflection. final Set targetsUsed = new Set(); @@ -1057,6 +1054,14 @@ class JavaScriptBackend extends Backend { } } + 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); @@ -1267,7 +1272,6 @@ class JavaScriptBackend extends Backend { super.onResolutionComplete(); computeMembersNeededForReflection(); rti.computeClassesNeedingRti(); - _registeredMetadata.clear(); } onTypeInferenceComplete() { @@ -2300,60 +2304,17 @@ class JavaScriptBackend extends Backend { reporter.log('Retaining metadata.'); compiler.libraryLoader.libraries.forEach(retainMetadataOf); - - if (enqueuer.isResolutionQueue) { - /// 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)); - } + for (Dependency dependency in metadataConstants) { + registerCompileTimeConstant(dependency.constant, + new EagerRegistry('EagerRegistry for ${dependency}', enqueuer)); + } + if (!enqueuer.isResolutionQueue) { metadataConstants.clear(); } } return true; } - /// Call [registerMetadataConstant] on all metadata from [elements]. - void processMetadata(Iterable elements, - void onMetadata(MetadataAnnotation metadata)) { - void processLibraryMetadata(LibraryElement library) { - if (_registeredMetadata.add(library)) { - library.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.enclosingClass != null) { - processElementMetadata(element.enclosingClass); - } else { - processLibraryMetadata(element.library); - } - } - } - - elements.forEach(processElementMetadata); - } - void onQueueClosed() { lookupMapAnalysis.onQueueClosed(); jsInteropAnalysis.onQueueClosed(); @@ -3076,8 +3037,6 @@ class Dependency { final Element annotatedElement; const Dependency(this.constant, this.annotatedElement); - - String toString() => '$annotatedElement:${constant.toStructuredText()}'; } class JavaScriptImpactStrategy extends ImpactStrategy { diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart index e88d927fdb8..fc53cb4158a 100644 --- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart +++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart @@ -64,11 +64,6 @@ class ConstantEmitter implements ConstantValueVisitor { return new jsAst.LiteralNull(); } - @override - jsAst.Expression visitNonConstant(NonConstantValue constant, [_]) { - return new jsAst.LiteralNull(); - } - static final _exponentialRE = new RegExp('^' '\([-+]?\)' // 1: sign '\([0-9]+\)' // 2: leading digit(s) diff --git a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart index dcab36a2390..6077e6d0579 100644 --- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart +++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart @@ -115,6 +115,10 @@ class JavaScriptConstantCompiler extends ConstantCompilerBase final Map nodeConstantMap = new Map(); + // Constants computed for metadata. + final Map metadataConstantMap = + new Map(); + JavaScriptConstantCompiler(Compiler compiler) : super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM); @@ -208,7 +212,15 @@ class JavaScriptConstantCompiler extends ConstantCompilerBase } ConstantValue getConstantValueForMetadata(MetadataAnnotation metadata) { - return getConstantValue(metadata.constant); + return getConstantValue(metadataConstantMap[metadata]); + } + + ConstantExpression compileMetadata( + MetadataAnnotation metadata, Node node, TreeElements elements) { + ConstantExpression constant = + super.compileMetadata(metadata, node, elements); + metadataConstantMap[metadata] = constant; + return constant; } void forgetElement(Element element) { @@ -218,6 +230,29 @@ class JavaScriptConstantCompiler extends ConstantCompilerBase element.node.accept(new ForgetConstantNodeVisitor(this)); } } + + @override + ConstantValue getConstantValue(ConstantExpression expression) { + assert(invariant(CURRENT_ELEMENT_SPANNABLE, expression != null, + message: "ConstantExpression is null in getConstantValue.")); + // TODO(johhniwinther): ensure expressions have been evaluated at this + // point. This can't be enabled today due to dartbug.com/26406. + if (compiler.serialization.supportsDeserialization) { + evaluate(expression); + } + ConstantValue value = super.getConstantValue(expression); + if (value == null && + expression != null && + expression.kind == ConstantExpressionKind.ERRONEOUS) { + // TODO(johnniwinther): When the Dart constant system sees a constant + // expression as erroneous but the JavaScript constant system finds it ok + // we have store a constant value for the erroneous constant expression. + // Ensure the computed constant expressions are always the same; that only + // the constant values may be different. + value = new NullConstantValue(); + } + return value; + } } class ForgetConstantElementVisitor @@ -226,6 +261,7 @@ class ForgetConstantElementVisitor void visitElement(Element e, JavaScriptConstantCompiler constants) { for (MetadataAnnotation data in e.implementation.metadata) { + constants.metadataConstantMap.remove(data); if (data.hasNode) { data.node.accept(new ForgetConstantNodeVisitor(constants)); } diff --git a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart index e2ebe39130a..448f9799222 100644 --- a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart +++ b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart @@ -5,7 +5,6 @@ /// Analysis to determine how to generate code for typed JavaScript interop. library compiler.src.js_backend.js_interop_analysis; -import '../common.dart'; import '../constants/values.dart' show ConstantValue, ConstructedConstantValue, StringConstantValue; import '../diagnostics/messages.dart' show MessageKind; @@ -55,8 +54,6 @@ class JsInteropAnalysis { void processJsInteropAnnotation(Element e) { for (MetadataAnnotation annotation in e.implementation.metadata) { - // TODO(johnniwinther): Avoid processing unresolved elements. - if (annotation.constant == null) continue; ConstantValue constant = backend.compiler.constants.getConstantValue(annotation.constant); if (constant == null || constant is! ConstructedConstantValue) continue; diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart index 9d86752a40b..c0f21c5a053 100644 --- a/pkg/compiler/lib/src/js_backend/namer.dart +++ b/pkg/compiler/lib/src/js_backend/namer.dart @@ -1671,11 +1671,6 @@ class ConstantNamingVisitor implements ConstantValueVisitor { add('null'); } - @override - void visitNonConstant(NonConstantValue constant, [_]) { - add('null'); - } - @override void visitInt(IntConstantValue constant, [_]) { // No `addRoot` since IntConstants are always inlined. @@ -1820,9 +1815,6 @@ class ConstantCanonicalHasher implements ConstantValueVisitor { @override int visitNull(NullConstantValue constant, [_]) => 1; - @override - int visitNonConstant(NonConstantValue constant, [_]) => 1; - @override int visitBool(BoolConstantValue constant, [_]) { return constant.isTrue ? 2 : 3; diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart index 27651c20e31..a2a0d7d5fcc 100644 --- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart +++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart @@ -76,10 +76,6 @@ class _CompareVisitor implements ConstantValueVisitor { return 0; } - int visitNonConstant(NonConstantValue a, NonConstantValue b) { - return 0; - } - int visitInt(IntConstantValue a, IntConstantValue b) { return a.primitiveValue.compareTo(b.primitiveValue); } @@ -193,14 +189,12 @@ class _KindVisitor implements ConstantValueVisitor { static const int INTERCEPTOR = 11; static const int SYNTHETIC = 12; static const int DEFERRED = 13; - static const int NONCONSTANT = 13; static int kind(ConstantValue constant) => constant.accept(const _KindVisitor(), null); int visitFunction(FunctionConstantValue a, _) => FUNCTION; int visitNull(NullConstantValue a, _) => NULL; - int visitNonConstant(NonConstantValue a, _) => NONCONSTANT; int visitInt(IntConstantValue a, _) => INT; int visitDouble(DoubleConstantValue a, _) => DOUBLE; int visitBool(BoolConstantValue a, _) => BOOL; diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart index e8f33402347..63b601d898b 100644 --- a/pkg/compiler/lib/src/native/enqueue.dart +++ b/pkg/compiler/lib/src/native/enqueue.dart @@ -318,7 +318,7 @@ abstract class NativeEnqueuerBase implements NativeEnqueuer { // TODO(sra): Better validation of the constant. if (fields.length != 1 || fields.single is! StringConstantValue) { reporter.internalError( - annotation, 'Annotations needs one string: ${annotation}'); + annotation, 'Annotations needs one string: ${annotation.node}'); } StringConstantValue specStringConstant = fields.single; String specString = specStringConstant.toDartString().slowToString(); @@ -326,7 +326,7 @@ abstract class NativeEnqueuerBase implements NativeEnqueuer { name = specString; } else { reporter.internalError( - annotation, 'Too many JSName annotations: ${annotation}'); + annotation, 'Too many JSName annotations: ${annotation.node}'); } } return name; diff --git a/pkg/compiler/lib/src/parser/element_listener.dart b/pkg/compiler/lib/src/parser/element_listener.dart index 6d9bd8252a9..6fe019cdae5 100644 --- a/pkg/compiler/lib/src/parser/element_listener.dart +++ b/pkg/compiler/lib/src/parser/element_listener.dart @@ -17,7 +17,6 @@ import '../elements/modelx.dart' EnumClassElementX, FieldElementX, LibraryElementX, - MetadataAnnotationX, NamedMixinApplicationElementX, VariableList; import '../id_generator.dart'; @@ -234,8 +233,8 @@ class ElementListener extends Listener { void endTopLevelDeclaration(Token token) { if (!metadata.isEmpty) { - MetadataAnnotationX first = metadata.first; - recoverableError(first.beginToken, 'Metadata not supported here.'); + recoverableError( + metadata.first.beginToken, 'Metadata not supported here.'); metadata.clear(); } } diff --git a/pkg/compiler/lib/src/patch_parser.dart b/pkg/compiler/lib/src/patch_parser.dart index 9f510363de3..a2246c426a0 100644 --- a/pkg/compiler/lib/src/patch_parser.dart +++ b/pkg/compiler/lib/src/patch_parser.dart @@ -128,7 +128,6 @@ import 'elements/modelx.dart' ClassElementX, GetterElementX, LibraryElementX, - MetadataAnnotationX, SetterElementX; import 'id_generator.dart'; import 'js_backend/js_backend.dart' show JavaScriptBackend; @@ -404,7 +403,7 @@ abstract class EagerAnnotationHandler { class NativeAnnotationHandler implements EagerAnnotationHandler { const NativeAnnotationHandler(); - String getNativeAnnotation(MetadataAnnotationX annotation) { + String getNativeAnnotation(MetadataAnnotation annotation) { if (annotation.beginToken != null && annotation.beginToken.next.value == 'Native') { // Skipping '@', 'Native', and '('. @@ -444,7 +443,7 @@ class NativeAnnotationHandler implements EagerAnnotationHandler { class JsInteropAnnotationHandler implements EagerAnnotationHandler { const JsInteropAnnotationHandler(); - bool hasJsNameAnnotation(MetadataAnnotationX annotation) => + bool hasJsNameAnnotation(MetadataAnnotation annotation) => annotation.beginToken != null && annotation.beginToken.next.value == 'JS'; bool apply( @@ -475,7 +474,7 @@ class JsInteropAnnotationHandler implements EagerAnnotationHandler { class PatchAnnotationHandler implements EagerAnnotationHandler { const PatchAnnotationHandler(); - PatchVersion getPatchVersion(MetadataAnnotationX annotation) { + PatchVersion getPatchVersion(MetadataAnnotation annotation) { if (annotation.beginToken != null) { if (annotation.beginToken.next.value == 'patch') { return const PatchVersion(null); diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart index e52b185806e..54bd4959ed0 100644 --- a/pkg/compiler/lib/src/resolution/registry.dart +++ b/pkg/compiler/lib/src/resolution/registry.dart @@ -334,6 +334,10 @@ class ResolutionRegistry extends Registry { worldImpact.registerStaticUse(staticUse); } + void registerMetadataConstant(MetadataAnnotation metadata) { + backend.registerMetadataConstant(metadata, metadata.annotatedElement, this); + } + /// Register the use of a type. void registerTypeUse(TypeUse typeUse) { worldImpact.registerTypeUse(typeUse); diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart index 2fd4e6850c4..f1ca6d02630 100644 --- a/pkg/compiler/lib/src/resolution/resolution.dart +++ b/pkg/compiler/lib/src/resolution/resolution.dart @@ -1088,6 +1088,7 @@ class ResolverTask extends CompilerTask { // and the annotated element instead. This will allow the backend to // retrieve the backend constant and only register metadata on the // elements for which it is needed. (Issue 17732). + registry.registerMetadataConstant(annotation); annotation.resolutionState = STATE_DONE; })); } diff --git a/pkg/compiler/lib/src/serialization/element_serialization.dart b/pkg/compiler/lib/src/serialization/element_serialization.dart index 8a2ad83eab4..b115ae0ed0f 100644 --- a/pkg/compiler/lib/src/serialization/element_serialization.dart +++ b/pkg/compiler/lib/src/serialization/element_serialization.dart @@ -120,23 +120,6 @@ class SerializerUtil { } } - /// Serialize the metadata of [element] into [encoder]. - static void serializeMetadata(Element element, ObjectEncoder encoder) { - if (element.metadata.isNotEmpty) { - ListEncoder list = encoder.createList(Key.METADATA); - for (MetadataAnnotation metadata in element.metadata) { - ObjectEncoder object = list.createObject(); - object.setElement(Key.ELEMENT, metadata.annotatedElement); - SourceSpan sourcePosition = metadata.sourcePosition; - // TODO(johnniwinther): What is the base URI here? - object.setUri(Key.URI, sourcePosition.uri, sourcePosition.uri); - object.setInt(Key.OFFSET, sourcePosition.begin); - object.setInt(Key.LENGTH, sourcePosition.end - sourcePosition.begin); - object.setConstant(Key.CONSTANT, metadata.constant); - } - } - } - /// Serialize the parent relation for [element] into [encoder], i.e library, /// enclosing class, and compilation unit references. static void serializeParentRelation(Element element, ObjectEncoder encoder) { @@ -242,7 +225,6 @@ class LibrarySerializer implements ElementSerializer { void serialize(LibraryElement element, ObjectEncoder encoder, SerializedElementKind kind) { - SerializerUtil.serializeMetadata(element, encoder); encoder.setUri( Key.CANONICAL_URI, element.canonicalUri, element.canonicalUri); encoder.setString(Key.LIBRARY_NAME, element.libraryName); @@ -270,7 +252,6 @@ class CompilationUnitSerializer implements ElementSerializer { void serialize(CompilationUnitElement element, ObjectEncoder encoder, SerializedElementKind kind) { - SerializerUtil.serializeMetadata(element, encoder); encoder.setElement(Key.LIBRARY, element.library); encoder.setUri( Key.URI, element.library.canonicalUri, element.script.resourceUri); @@ -318,7 +299,6 @@ class ClassSerializer implements ElementSerializer { void serialize( ClassElement element, ObjectEncoder encoder, SerializedElementKind kind) { - SerializerUtil.serializeMetadata(element, encoder); encoder.setElement(Key.LIBRARY, element.library); encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit); encoder.setString(Key.NAME, element.name); @@ -327,7 +307,6 @@ class ClassSerializer implements ElementSerializer { encoder.setBool(Key.IS_ABSTRACT, element.isAbstract); SerializerUtil.serializeMembers(getMembers(element), encoder); encoder.setBool(Key.IS_PROXY, element.isProxy); - encoder.setBool(Key.IS_INJECTED, element.isInjected); if (kind == SerializedElementKind.ENUM) { EnumClassElement enumClass = element; encoder.setElements(Key.FIELDS, enumClass.enumValues); @@ -389,14 +368,12 @@ class ConstructorSerializer implements ElementSerializer { if (kind == SerializedElementKind.FORWARDING_CONSTRUCTOR) { encoder.setElement(Key.ELEMENT, element.definingConstructor); } else { - SerializerUtil.serializeMetadata(element, encoder); encoder.setType(Key.TYPE, element.type); encoder.setString(Key.NAME, element.name); SerializerUtil.serializePosition(element, encoder); SerializerUtil.serializeParameters(element, encoder); encoder.setBool(Key.IS_CONST, element.isConst); encoder.setBool(Key.IS_EXTERNAL, element.isExternal); - encoder.setBool(Key.IS_INJECTED, element.isInjected); if (element.isConst && !element.isFromEnvironmentConstructor) { ConstantConstructor constantConstructor = element.constantConstructor; ObjectEncoder constantEncoder = encoder.createObject(Key.CONSTRUCTOR); @@ -442,12 +419,10 @@ class FieldSerializer implements ElementSerializer { void serialize( FieldElement element, ObjectEncoder encoder, SerializedElementKind kind) { encoder.setString(Key.NAME, element.name); - SerializerUtil.serializeMetadata(element, encoder); SerializerUtil.serializePosition(element, encoder); encoder.setType(Key.TYPE, element.type); encoder.setBool(Key.IS_FINAL, element.isFinal); encoder.setBool(Key.IS_CONST, element.isConst); - encoder.setBool(Key.IS_INJECTED, element.isInjected); ConstantExpression constant = element.constant; if (constant != null) { encoder.setConstant(Key.CONSTANT, constant); @@ -494,7 +469,6 @@ class FunctionSerializer implements ElementSerializer { void serialize(FunctionElement element, ObjectEncoder encoder, SerializedElementKind kind) { encoder.setString(Key.NAME, element.name); - SerializerUtil.serializeMetadata(element, encoder); SerializerUtil.serializePosition(element, encoder); SerializerUtil.serializeParameters(element, encoder); encoder.setType(Key.TYPE, element.type); @@ -505,7 +479,6 @@ class FunctionSerializer implements ElementSerializer { SerializerUtil.serializeParentRelation(element, encoder); encoder.setBool(Key.IS_EXTERNAL, element.isExternal); encoder.setBool(Key.IS_ABSTRACT, element.isAbstract); - encoder.setBool(Key.IS_INJECTED, element.isInjected); if (element.isLocal) { LocalFunctionElement localFunction = element; encoder.setElement( @@ -527,7 +500,6 @@ class TypedefSerializer implements ElementSerializer { void serialize(TypedefElement element, ObjectEncoder encoder, SerializedElementKind kind) { encoder.setString(Key.NAME, element.name); - SerializerUtil.serializeMetadata(element, encoder); SerializerUtil.serializePosition(element, encoder); encoder.setType(Key.ALIAS, element.alias); encoder.setElement(Key.LIBRARY, element.library); @@ -550,7 +522,6 @@ class TypeVariableSerializer implements ElementSerializer { SerializedElementKind kind) { encoder.setElement(Key.TYPE_DECLARATION, element.typeDeclaration); encoder.setString(Key.NAME, element.name); - SerializerUtil.serializeMetadata(element, encoder); SerializerUtil.serializePosition(element, encoder); encoder.setType(Key.TYPE, element.type); encoder.setInt(Key.INDEX, element.index); @@ -574,7 +545,6 @@ class ParameterSerializer implements ElementSerializer { SerializedElementKind kind) { encoder.setElement(Key.FUNCTION, element.functionDeclaration); encoder.setString(Key.NAME, element.name); - SerializerUtil.serializeMetadata(element, encoder); SerializerUtil.serializePosition(element, encoder); encoder.setType(Key.TYPE, element.type); encoder.setBool(Key.IS_OPTIONAL, element.isOptional); @@ -603,7 +573,6 @@ class LocalVariableSerializer implements ElementSerializer { void serialize(LocalVariableElement element, ObjectEncoder encoder, SerializedElementKind kind) { encoder.setString(Key.NAME, element.name); - SerializerUtil.serializeMetadata(element, encoder); SerializerUtil.serializePosition(element, encoder); encoder.setType(Key.TYPE, element.type); encoder.setBool(Key.IS_FINAL, element.isFinal); @@ -628,7 +597,6 @@ class ImportSerializer implements ElementSerializer { void serialize(ImportElement element, ObjectEncoder encoder, SerializedElementKind kind) { - SerializerUtil.serializeMetadata(element, encoder); encoder.setElement(Key.LIBRARY, element.library); encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit); encoder.setElement(Key.LIBRARY_DEPENDENCY, element.importedLibrary); @@ -653,7 +621,6 @@ class ExportSerializer implements ElementSerializer { void serialize(ExportElement element, ObjectEncoder encoder, SerializedElementKind kind) { - SerializerUtil.serializeMetadata(element, encoder); encoder.setElement(Key.LIBRARY, element.library); encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit); encoder.setElement(Key.LIBRARY_DEPENDENCY, element.exportedLibrary); diff --git a/pkg/compiler/lib/src/serialization/equivalence.dart b/pkg/compiler/lib/src/serialization/equivalence.dart index a7c08b5b09f..a1f341c0241 100644 --- a/pkg/compiler/lib/src/serialization/equivalence.dart +++ b/pkg/compiler/lib/src/serialization/equivalence.dart @@ -1832,12 +1832,3 @@ class NodeEquivalenceVisitor implements Visitor1 { throw new UnsupportedError('Unexpected nodes: $node1 <> $node2'); } } - -bool areMetadataAnnotationsEquivalent( - MetadataAnnotation metadata1, MetadataAnnotation metadata2) { - if (metadata1 == metadata2) return true; - if (metadata1 == null || metadata2 == null) return false; - return areElementsEquivalent( - metadata1.annotatedElement, metadata2.annotatedElement) && - areConstantsEquivalent(metadata1.constant, metadata2.constant); -} diff --git a/pkg/compiler/lib/src/serialization/keys.dart b/pkg/compiler/lib/src/serialization/keys.dart index fb5151b09a4..179b72716f0 100644 --- a/pkg/compiler/lib/src/serialization/keys.dart +++ b/pkg/compiler/lib/src/serialization/keys.dart @@ -59,7 +59,6 @@ class Key { static const Key IS_EMPTY = const Key('isEmpty'); static const Key IS_EXTERNAL = const Key('isExternal'); static const Key IS_FINAL = const Key('isFinal'); - static const Key IS_INJECTED = const Key('isInjected'); static const Key IS_NAMED = const Key('isNamed'); static const Key IS_OPERATOR = const Key('isOperator'); static const Key IS_OPTIONAL = const Key('isOptional'); @@ -84,7 +83,6 @@ class Key { static const Key LISTS = const Key('lists'); static const Key MAPS = const Key('maps'); static const Key MEMBERS = const Key('members'); - static const Key METADATA = const Key('metadata'); static const Key MIXIN = const Key('mixin'); static const Key MIXINS = const Key('mixins'); static const Key NAME = const Key('name'); diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart index c909f9acf56..a03ef2f2b12 100644 --- a/pkg/compiler/lib/src/serialization/modelz.dart +++ b/pkg/compiler/lib/src/serialization/modelz.dart @@ -112,6 +112,7 @@ abstract class ElementZ extends Element with ElementCommon { @override bool get isTopLevel => false; + // TODO(johnniwinther): Support metadata. @override Iterable get metadata => const []; @@ -121,7 +122,6 @@ abstract class ElementZ extends Element with ElementCommon { abstract class DeserializedElementZ extends ElementZ { ObjectDecoder _decoder; - List _metadata; DeserializedElementZ(this._decoder); @@ -147,27 +147,6 @@ abstract class DeserializedElementZ extends ElementZ { } return new SourceSpan(uri, offset, offset + length); } - - @override - Iterable get metadata { - if (_metadata == null) { - _metadata = []; - ListDecoder list = _decoder.getList(Key.METADATA, isOptional: true); - if (list != null) { - for (int index = 0; index < list.length; index++) { - ObjectDecoder object = list.getObject(index); - Element element = object.getElement(Key.ELEMENT); - Uri uri = object.getUri(Key.URI); - int offset = object.getInt(Key.OFFSET); - int length = object.getInt(Key.LENGTH); - ConstantExpression constant = object.getConstant(Key.CONSTANT); - _metadata.add(new MetadataAnnotationZ( - element, new SourceSpan(uri, offset, offset + length), constant)); - } - } - } - return _metadata; - } } /// Deserializer for a collection of member elements serialized as a map from @@ -966,9 +945,6 @@ class ClassElementZ extends DeserializedElementZ @override bool get isProxy => _decoder.getBool(Key.IS_PROXY); - @override - bool get isInjected => _decoder.getBool(Key.IS_INJECTED); - @override bool get isUnnamedMixinApplication => false; @@ -1504,9 +1480,6 @@ abstract class MemberElementMixin @override List get nestedClosures => []; - - @override - bool get isInjected => _decoder.getBool(Key.IS_INJECTED); } abstract class FieldElementZ extends DeserializedElementZ @@ -2290,25 +2263,3 @@ class PrefixElementZ extends DeserializedElementZ return _unsupported('lookupLocalMember'); } } - -class MetadataAnnotationZ implements MetadataAnnotation { - final Element annotatedElement; - final SourceSpan sourcePosition; - final ConstantExpression constant; - - MetadataAnnotationZ( - this.annotatedElement, this.sourcePosition, this.constant); - - @override - MetadataAnnotation ensureResolved(Resolution resolution) { - // Do nothing. - } - - @override - Node get node => throw new UnsupportedError('${this}.node'); - - @override - bool get hasNode => false; - - String toString() => 'MetadataAnnotationZ(${constant.toDartText()})'; -} diff --git a/pkg/compiler/lib/src/types/constants.dart b/pkg/compiler/lib/src/types/constants.dart index d66a31c3b6f..a3b2faa917f 100644 --- a/pkg/compiler/lib/src/types/constants.dart +++ b/pkg/compiler/lib/src/types/constants.dart @@ -104,11 +104,6 @@ class ConstantValueTypeMasks extends ConstantValueVisitor { return compiler.typesTask.nullType; } - @override - TypeMask visitNonConstant(NonConstantValue constant, Compiler compiler) { - return compiler.typesTask.nullType; - } - @override TypeMask visitString(StringConstantValue constant, Compiler compiler) { return compiler.typesTask.stringType; diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart index fc08b6b82f9..dffab8af88a 100644 --- a/tests/compiler/dart2js/mirrors_used_test.dart +++ b/tests/compiler/dart2js/mirrors_used_test.dart @@ -127,22 +127,18 @@ void main() { }); } - int metadataCount = 0; + // There should at least be one metadata constant: + // 1. The constructed constant for 'MirrorsUsed'. + Expect.isTrue(backend.metadataConstants.length >= 1); + Set compiledConstants = backend.constants.compiledConstants; // Make sure that most of the metadata constants aren't included in the // generated code. - backend.processMetadata( - compiler.enqueuer.resolution.processedElements, (metadata) { - ConstantValue constant = - backend.constants.getConstantValueForMetadata(metadata); + for (var dependency in backend.metadataConstants) { + ConstantValue constant = dependency.constant; Expect.isFalse(compiledConstants.contains(constant), constant.toStructuredText()); - metadataCount++; - }); - - // There should at least be one metadata constant: - // 1. The constructed constant for 'MirrorsUsed'. - Expect.isTrue(metadataCount >= 1); + } // The type literal 'Foo' is both used as metadata, and as a plain value in // the program. Make sure that it isn't duplicated. diff --git a/tests/compiler/dart2js/serialization/equivalence_test.dart b/tests/compiler/dart2js/serialization/equivalence_test.dart index 91abd275067..bd903dab4d1 100644 --- a/tests/compiler/dart2js/serialization/equivalence_test.dart +++ b/tests/compiler/dart2js/serialization/equivalence_test.dart @@ -248,16 +248,6 @@ checkElementLists(Object object1, Object object2, String property, list1, list2, checkElementProperties); } -/// Check the equivalence of the two metadata annotations, [metadata1] and -/// [metadata2]. -/// -/// Uses [object1], [object2] and [property] to provide context for failures. -checkMetadata(Object object1, Object object2, String property, - MetadataAnnotation metadata1, MetadataAnnotation metadata2) { - check(object1, object2, property, - metadata1, metadata2, areMetadataAnnotationsEquivalent); -} - /// Visitor that checks for equivalence of [Element] properties. class ElementPropertyEquivalence extends BaseElementVisitor { const ElementPropertyEquivalence(); @@ -287,8 +277,6 @@ class ElementPropertyEquivalence extends BaseElementVisitor { element1.isClassMember, element2.isClassMember); check(element1, element2, 'isInstanceMember', element1.isInstanceMember, element2.isInstanceMember); - checkListEquivalence(element1, element2, 'metadata', - element1.metadata, element2.metadata, checkMetadata); } @override @@ -442,10 +430,6 @@ class ElementPropertyEquivalence extends BaseElementVisitor { element1.isAbstract, element2.isAbstract); check(element1, element2, 'isUnnamedMixinApplication', element1.isUnnamedMixinApplication, element2.isUnnamedMixinApplication); - check(element1, element2, 'isProxy', - element1.isProxy, element2.isProxy); - check(element1, element2, 'isInjected', - element1.isInjected, element2.isInjected); check(element1, element2, 'isEnumClass', element1.isEnumClass, element2.isEnumClass); if (element1.isEnumClass) { @@ -531,8 +515,6 @@ class ElementPropertyEquivalence extends BaseElementVisitor { element1.isStatic, element2.isStatic); check(element1, element2, 'isInstanceMember', element1.isInstanceMember, element2.isInstanceMember); - check(element1, element2, 'isInjected', - element1.isInjected, element2.isInjected); checkElementIdentities( element1, element2, 'library', @@ -566,8 +548,6 @@ class ElementPropertyEquivalence extends BaseElementVisitor { element1, element2, 'asyncMarker', element1.asyncMarker, element2.asyncMarker); - check(element1, element2, 'isInjected', - element1.isInjected, element2.isInjected); checkElementIdentities( element1, element2, 'library', @@ -672,8 +652,6 @@ class ElementPropertyEquivalence extends BaseElementVisitor { element2.immediateRedirectionTarget); checkElementIdentities(element1, element2, 'redirectionDeferredPrefix', element1.redirectionDeferredPrefix, element2.redirectionDeferredPrefix); - check(element1, element2, 'isInjected', - element1.isInjected, element2.isInjected); } @override diff --git a/tests/compiler/dart2js/serialization/model_test.dart b/tests/compiler/dart2js/serialization/model_test.dart index a73f3d170b3..5dab06eed9c 100644 --- a/tests/compiler/dart2js/serialization/model_test.dart +++ b/tests/compiler/dart2js/serialization/model_test.dart @@ -32,7 +32,7 @@ main(List args) { resolutionInputs: serializedData.toUris()); } else { Uri entryPoint = Uri.parse('memory:main.dart'); - await arguments.forEachTest(serializedData, TESTS, checkModels); + arguments.forEachTest(serializedData, TESTS, checkModels); } }); } @@ -44,6 +44,11 @@ Future checkModels( int index, Test test, bool verbose: false}) async { + if (test != null && test.name == 'Disable tree shaking through reflection') { + // TODO(johnniwinther): Support serialization of metadata. + return; + } + String testDescription = test != null ? test.name : '${entryPoint}'; String id = index != null ? '$index: ' : ''; print('------------------------------------------------------------------'); diff --git a/tests/compiler/dart2js/serialization/test_helper.dart b/tests/compiler/dart2js/serialization/test_helper.dart index a6dddf9069a..34f40aa76b4 100644 --- a/tests/compiler/dart2js/serialization/test_helper.dart +++ b/tests/compiler/dart2js/serialization/test_helper.dart @@ -436,7 +436,6 @@ void checkSets( String messagePrefix, bool sameElement(a, b), {bool failOnUnfound: true, - bool failOnExtra: true, bool verbose: false, void onSameElement(a, b)}) { List common = []; @@ -459,8 +458,7 @@ void checkSets( String message = sb.toString(); if (unfound.isNotEmpty || remaining.isNotEmpty) { - if ((failOnUnfound && unfound.isNotEmpty) || - (failOnExtra && remaining.isNotEmpty)) { + if (failOnUnfound || remaining.isNotEmpty) { Expect.fail(message); } else { print(message);