blob: 5bfae8b0f77d798fb9f98ac2a003c3101ab80119 [file] [log] [blame]
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library dart2js.serialization.task;
import 'dart:async' show EventSink, Future;
import '../common/resolution.dart' show ResolutionImpact, ResolutionWorkItem;
import '../common/tasks.dart' show CompilerTask;
import '../compiler.dart' show Compiler;
import '../elements/elements.dart';
import '../enqueue.dart' show ResolutionEnqueuer;
import '../universe/world_impact.dart' show WorldImpact;
import 'json_serializer.dart';
import 'serialization.dart';
import 'system.dart';
/// A deserializer that can load a library element by reading it's information
/// from a serialized form.
abstract class LibraryDeserializer {
/// Loads the [LibraryElement] associated with a library under [uri], or null
/// if no serialized information is available for the given library.
Future<LibraryElement> readLibrary(Uri uri);
}
/// Task that supports deserialization of elements.
class SerializationTask extends CompilerTask implements LibraryDeserializer {
final Compiler compiler;
SerializationTask(Compiler compiler)
: compiler = compiler,
super(compiler.measurer);
DeserializerSystem deserializer;
String get name => 'Serialization';
/// If `true`, data must be retained to support serialization.
// TODO(johnniwinther): Make this more precise in terms of what needs to be
// retained, for instance impacts, resolution data etc.
bool supportSerialization = false;
/// Set this flag to also deserialize [ResolvedAst]s and [ResolutionImpact]s
/// in `resolveOnly` mode. Use this for testing only.
bool deserializeCompilationDataForTesting = false;
/// If `true`, deserialized data is supported.
bool get supportsDeserialization => deserializer != null;
/// Returns the [LibraryElement] for [resolvedUri] if available from
/// serialization.
Future<LibraryElement> readLibrary(Uri resolvedUri) {
if (deserializer == null) return new Future<LibraryElement>.value();
return deserializer.readLibrary(resolvedUri);
}
/// Returns `true` if [element] has been deserialized.
bool isDeserialized(Element element) {
return deserializer != null && deserializer.isDeserialized(element);
}
bool hasResolutionImpact(Element element) {
return deserializer != null && deserializer.hasResolutionImpact(element);
}
ResolutionImpact getResolutionImpact(Element element) {
return deserializer != null
? deserializer.getResolutionImpact(element)
: null;
}
/// Creates the [ResolutionWorkItem] for the deserialized [element].
ResolutionWorkItem createResolutionWorkItem(Element element) {
assert(deserializer != null);
assert(isDeserialized(element));
return new DeserializedResolutionWorkItem(
element, deserializer.computeWorldImpact(element));
}
bool hasResolvedAst(ExecutableElement element) {
return deserializer != null ? deserializer.hasResolvedAst(element) : false;
}
ResolvedAst getResolvedAst(ExecutableElement element) {
return deserializer != null ? deserializer.getResolvedAst(element) : null;
}
Serializer createSerializer(Iterable<LibraryElement> libraries) {
return measure(() {
assert(supportSerialization);
Serializer serializer =
new Serializer(shouldInclude: (e) => libraries.contains(e.library));
SerializerPlugin backendSerializer =
compiler.backend.serialization.serializer;
serializer.plugins.add(backendSerializer);
serializer.plugins.add(new ResolutionImpactSerializer(
compiler.resolution, backendSerializer));
serializer.plugins.add(new ResolvedAstSerializerPlugin(
compiler.resolution, backendSerializer));
for (LibraryElement library in libraries) {
serializer.serialize(library);
}
return serializer;
});
}
void serializeToSink(
EventSink<String> sink, Iterable<LibraryElement> libraries) {
measure(() {
sink
..add(createSerializer(libraries)
.toText(const JsonSerializationEncoder()))
..close();
});
}
void deserializeFromText(Uri sourceUri, String serializedData) {
measure(() {
if (deserializer == null) {
deserializer = new ResolutionDeserializerSystem(compiler,
deserializeCompilationDataForTesting:
deserializeCompilationDataForTesting);
}
ResolutionDeserializerSystem deserializerImpl = deserializer;
DeserializationContext context = deserializerImpl.deserializationContext;
Deserializer dataDeserializer = new Deserializer.fromText(
context, sourceUri, serializedData, const JsonSerializationDecoder());
context.deserializers.add(dataDeserializer);
});
}
}
/// A [ResolutionWorkItem] for a deserialized element.
///
/// This will not resolve the element but only compute the [WorldImpact].
class DeserializedResolutionWorkItem implements ResolutionWorkItem {
final Element element;
final WorldImpact worldImpact;
bool _isAnalyzed = false;
DeserializedResolutionWorkItem(this.element, this.worldImpact);
@override
bool get isAnalyzed => _isAnalyzed;
@override
WorldImpact run(Compiler compiler, ResolutionEnqueuer world) {
_isAnalyzed = true;
world.registerProcessedElement(element);
return worldImpact;
}
}
/// The interface for a system that supports deserialization of libraries and
/// elements.
abstract class DeserializerSystem {
Future<LibraryElement> readLibrary(Uri resolvedUri);
bool isDeserialized(Element element);
bool hasResolvedAst(ExecutableElement element);
ResolvedAst getResolvedAst(ExecutableElement element);
bool hasResolutionImpact(Element element);
ResolutionImpact getResolutionImpact(Element element);
WorldImpact computeWorldImpact(Element element);
}