mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:59:47 +00:00
Serialize ResolutionImpact instead of WorldImpact.
R=sigmund@google.com Review URL: https://codereview.chromium.org/1839243003 .
This commit is contained in:
parent
c53ec0971b
commit
27b2c36ec1
|
@ -190,6 +190,9 @@ abstract class Resolution {
|
|||
ResolutionWorkItem createWorkItem(
|
||||
Element element, ItemCompilationContext compilationContext);
|
||||
|
||||
/// Returns the precomputed [ResolutionImpact] for [element].
|
||||
ResolutionImpact getResolutionImpact(Element element);
|
||||
|
||||
/// Returns the precomputed [WorldImpact] for [element].
|
||||
WorldImpact getWorldImpact(Element element);
|
||||
|
||||
|
|
|
@ -1957,6 +1957,8 @@ class _CompilerDiagnosticReporter extends DiagnosticReporter {
|
|||
// TODO(johnniwinther): Move [ResolverTask] here.
|
||||
class _CompilerResolution implements Resolution {
|
||||
final Compiler compiler;
|
||||
final Map<Element, ResolutionImpact> _resolutionImpactCache =
|
||||
<Element, ResolutionImpact>{};
|
||||
final Map<Element, WorldImpact> _worldImpactCache = <Element, WorldImpact>{};
|
||||
|
||||
_CompilerResolution(this.compiler);
|
||||
|
@ -2000,6 +2002,14 @@ class _CompilerResolution implements Resolution {
|
|||
return compiler.resolver.resolveTypeAnnotation(element, node);
|
||||
}
|
||||
|
||||
@override
|
||||
ResolutionImpact getResolutionImpact(Element element) {
|
||||
ResolutionImpact resolutionImpact = _resolutionImpactCache[element];
|
||||
assert(invariant(element, resolutionImpact != null,
|
||||
message: "ResolutionImpact not available for $element."));
|
||||
return resolutionImpact;
|
||||
}
|
||||
|
||||
@override
|
||||
WorldImpact getWorldImpact(Element element) {
|
||||
WorldImpact worldImpact = _worldImpactCache[element];
|
||||
|
@ -2016,6 +2026,14 @@ class _CompilerResolution implements Resolution {
|
|||
assert(invariant(element, !element.isSynthesized || tree == null));
|
||||
ResolutionImpact resolutionImpact =
|
||||
compiler.resolver.resolve(element);
|
||||
if (compiler.serialization.supportSerialization) {
|
||||
// [ResolutionImpact] is currently only used by serialization. The
|
||||
// enqueuer uses the [WorldImpact] which is always cached.
|
||||
// TODO(johnniwinther): Align these use cases better; maybe only
|
||||
// cache [ResolutionImpact] and let the enqueuer transform it into
|
||||
// a [WorldImpact].
|
||||
_resolutionImpactCache[element] = resolutionImpact;
|
||||
}
|
||||
if (tree != null && !compiler.options.analyzeSignaturesOnly) {
|
||||
// TODO(het): don't do this if suppressWarnings is on, currently we have
|
||||
// to do it because the typechecker also sets types
|
||||
|
@ -2035,6 +2053,7 @@ class _CompilerResolution implements Resolution {
|
|||
assert(invariant(element, _worldImpactCache[element] != null,
|
||||
message: "WorldImpact not computed for $element."));
|
||||
_worldImpactCache[element] = const WorldImpact();
|
||||
_resolutionImpactCache.remove(element);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -2042,6 +2061,7 @@ class _CompilerResolution implements Resolution {
|
|||
for (Element element in _worldImpactCache.keys) {
|
||||
_worldImpactCache[element] = const WorldImpact();
|
||||
}
|
||||
_resolutionImpactCache.clear();
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -5,26 +5,58 @@
|
|||
library dart2js.serialization.impact;
|
||||
|
||||
import '../dart_types.dart';
|
||||
import '../common/resolution.dart';
|
||||
import '../constants/expressions.dart';
|
||||
import '../elements/elements.dart';
|
||||
import '../universe/call_structure.dart';
|
||||
import '../universe/selector.dart';
|
||||
import '../universe/world_impact.dart';
|
||||
import '../universe/use.dart';
|
||||
import '../util/enumset.dart';
|
||||
|
||||
import 'keys.dart';
|
||||
import 'serialization.dart';
|
||||
|
||||
/// Visitor that serializes a [WorldImpact] object using an [ObjectEncoder].
|
||||
/// Visitor that serializes a [ResolutionImpact] object using an
|
||||
/// [ObjectEncoder].
|
||||
class ImpactSerializer implements WorldImpactVisitor {
|
||||
final ObjectEncoder objectEncoder;
|
||||
final ListEncoder staticUses;
|
||||
final ListEncoder dynamicUses;
|
||||
final ListEncoder typeUses;
|
||||
|
||||
ImpactSerializer(ObjectEncoder objectEncoder)
|
||||
: staticUses = objectEncoder.createList(Key.STATIC_USES),
|
||||
: this.objectEncoder = objectEncoder,
|
||||
staticUses = objectEncoder.createList(Key.STATIC_USES),
|
||||
dynamicUses = objectEncoder.createList(Key.DYNAMIC_USES),
|
||||
typeUses = objectEncoder.createList(Key.TYPE_USES);
|
||||
|
||||
void serialize(ResolutionImpact resolutionImpact) {
|
||||
resolutionImpact.apply(this);
|
||||
objectEncoder.setStrings(Key.SYMBOLS, resolutionImpact.constSymbolNames);
|
||||
objectEncoder.setConstants(
|
||||
Key.CONSTANTS, resolutionImpact.constantLiterals);
|
||||
objectEncoder.setEnums(Key.FEATURES, resolutionImpact.features);
|
||||
if (resolutionImpact.listLiterals.isNotEmpty) {
|
||||
ListEncoder encoder = objectEncoder.createList(Key.LISTS);
|
||||
for (ListLiteralUse use in resolutionImpact.listLiterals) {
|
||||
ObjectEncoder useEncoder = encoder.createObject();
|
||||
useEncoder.setType(Key.TYPE, use.type);
|
||||
useEncoder.setBool(Key.IS_CONST, use.isConstant);
|
||||
useEncoder.setBool(Key.IS_EMPTY, use.isEmpty);
|
||||
}
|
||||
}
|
||||
if (resolutionImpact.mapLiterals.isNotEmpty) {
|
||||
ListEncoder encoder = objectEncoder.createList(Key.MAPS);
|
||||
for (MapLiteralUse use in resolutionImpact.mapLiterals) {
|
||||
ObjectEncoder useEncoder = encoder.createObject();
|
||||
useEncoder.setType(Key.TYPE, use.type);
|
||||
useEncoder.setBool(Key.IS_CONST, use.isConstant);
|
||||
useEncoder.setBool(Key.IS_EMPTY, use.isEmpty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitDynamicUse(DynamicUse dynamicUse) {
|
||||
ObjectEncoder object = dynamicUses.createObject();
|
||||
|
@ -66,22 +98,47 @@ class ImpactSerializer implements WorldImpactVisitor {
|
|||
}
|
||||
|
||||
/// A deserialized [WorldImpact] object.
|
||||
class DeserializedWorldImpact extends WorldImpact with WorldImpactBuilder {}
|
||||
class DeserializedResolutionImpact extends WorldImpact
|
||||
implements ResolutionImpact {
|
||||
final Iterable<String> constSymbolNames;
|
||||
final Iterable<ConstantExpression> constantLiterals;
|
||||
final Iterable<DynamicUse> dynamicUses;
|
||||
final EnumSet<Feature> _features;
|
||||
final Iterable<ListLiteralUse> listLiterals;
|
||||
final Iterable<MapLiteralUse> mapLiterals;
|
||||
final Iterable<StaticUse> staticUses;
|
||||
final Iterable<TypeUse> typeUses;
|
||||
|
||||
DeserializedResolutionImpact({
|
||||
this.constSymbolNames,
|
||||
this.constantLiterals,
|
||||
this.dynamicUses,
|
||||
EnumSet<Feature> features,
|
||||
this.listLiterals,
|
||||
this.mapLiterals,
|
||||
this.staticUses,
|
||||
this.typeUses})
|
||||
: this._features = features;
|
||||
|
||||
Iterable<Feature> get features => _features.iterable(Feature.values);
|
||||
}
|
||||
|
||||
class ImpactDeserializer {
|
||||
/// Deserializes a [WorldImpact] from [objectDecoder].
|
||||
static WorldImpact deserializeImpact(ObjectDecoder objectDecoder) {
|
||||
DeserializedWorldImpact worldImpact = new DeserializedWorldImpact();
|
||||
ListDecoder staticUses = objectDecoder.getList(Key.STATIC_USES);
|
||||
for (int index = 0; index < staticUses.length; index++) {
|
||||
ObjectDecoder object = staticUses.getObject(index);
|
||||
static ResolutionImpact deserializeImpact(ObjectDecoder objectDecoder) {
|
||||
ListDecoder staticUseDecoder = objectDecoder.getList(Key.STATIC_USES);
|
||||
List<StaticUse> staticUses = <StaticUse>[];
|
||||
for (int index = 0; index < staticUseDecoder.length; index++) {
|
||||
ObjectDecoder object = staticUseDecoder.getObject(index);
|
||||
StaticUseKind kind = object.getEnum(Key.KIND, StaticUseKind.values);
|
||||
Element element = object.getElement(Key.ELEMENT);
|
||||
worldImpact.registerStaticUse(new StaticUse.internal(element, kind));
|
||||
staticUses.add(new StaticUse.internal(element, kind));
|
||||
}
|
||||
ListDecoder dynamicUses = objectDecoder.getList(Key.DYNAMIC_USES);
|
||||
for (int index = 0; index < dynamicUses.length; index++) {
|
||||
ObjectDecoder object = dynamicUses.getObject(index);
|
||||
|
||||
ListDecoder dynamicUseDecoder = objectDecoder.getList(Key.DYNAMIC_USES);
|
||||
List<DynamicUse> dynamicUses = <DynamicUse>[];
|
||||
for (int index = 0; index < dynamicUseDecoder.length; index++) {
|
||||
ObjectDecoder object = dynamicUseDecoder.getObject(index);
|
||||
SelectorKind kind = object.getEnum(Key.KIND, SelectorKind.values);
|
||||
int argumentCount = object.getInt(Key.ARGUMENTS);
|
||||
List<String> namedArguments =
|
||||
|
@ -89,7 +146,7 @@ class ImpactDeserializer {
|
|||
String name = object.getString(Key.NAME);
|
||||
bool isSetter = object.getBool(Key.IS_SETTER);
|
||||
LibraryElement library = object.getElement(Key.LIBRARY, isOptional: true);
|
||||
worldImpact.registerDynamicUse(
|
||||
dynamicUses.add(
|
||||
new DynamicUse(
|
||||
new Selector(
|
||||
kind,
|
||||
|
@ -97,13 +154,63 @@ class ImpactDeserializer {
|
|||
new CallStructure(argumentCount, namedArguments)),
|
||||
null));
|
||||
}
|
||||
ListDecoder typeUses = objectDecoder.getList(Key.TYPE_USES);
|
||||
for (int index = 0; index < typeUses.length; index++) {
|
||||
ObjectDecoder object = typeUses.getObject(index);
|
||||
|
||||
ListDecoder typeUseDecoder = objectDecoder.getList(Key.TYPE_USES);
|
||||
List<TypeUse> typeUses = <TypeUse>[];
|
||||
for (int index = 0; index < typeUseDecoder.length; index++) {
|
||||
ObjectDecoder object = typeUseDecoder.getObject(index);
|
||||
TypeUseKind kind = object.getEnum(Key.KIND, TypeUseKind.values);
|
||||
DartType type = object.getType(Key.TYPE);
|
||||
worldImpact.registerTypeUse(new TypeUse.internal(type, kind));
|
||||
typeUses.add(new TypeUse.internal(type, kind));
|
||||
}
|
||||
return worldImpact;
|
||||
|
||||
List<String> constSymbolNames =
|
||||
objectDecoder.getStrings(Key.SYMBOLS, isOptional: true);
|
||||
|
||||
List<ConstantExpression> constantLiterals =
|
||||
objectDecoder.getConstants(Key.CONSTANTS, isOptional: true);
|
||||
|
||||
EnumSet<Feature> features =
|
||||
objectDecoder.getEnums(Key.FEATURES, isOptional: true);
|
||||
|
||||
ListDecoder listLiteralDecoder =
|
||||
objectDecoder.getList(Key.LISTS, isOptional: true);
|
||||
List<ListLiteralUse> listLiterals = const <ListLiteralUse>[];
|
||||
if (listLiteralDecoder != null) {
|
||||
listLiterals = <ListLiteralUse>[];
|
||||
for (int i = 0; i < listLiteralDecoder.length; i++) {
|
||||
ObjectDecoder useDecoder = listLiteralDecoder.getObject(i);
|
||||
DartType type = useDecoder.getType(Key.TYPE);
|
||||
bool isConstant = useDecoder.getBool(Key.IS_CONST);
|
||||
bool isEmpty = useDecoder.getBool(Key.IS_EMPTY);
|
||||
listLiterals.add(new ListLiteralUse(
|
||||
type, isConstant: isConstant, isEmpty: isEmpty));
|
||||
}
|
||||
}
|
||||
|
||||
ListDecoder mapLiteralDecoder =
|
||||
objectDecoder.getList(Key.LISTS, isOptional: true);
|
||||
List<MapLiteralUse> mapLiterals = const <MapLiteralUse>[];
|
||||
if (listLiteralDecoder != null) {
|
||||
mapLiterals = <MapLiteralUse>[];
|
||||
for (int i = 0; i < mapLiteralDecoder.length; i++) {
|
||||
ObjectDecoder useDecoder = mapLiteralDecoder.getObject(i);
|
||||
DartType type = useDecoder.getType(Key.TYPE);
|
||||
bool isConstant = useDecoder.getBool(Key.IS_CONST);
|
||||
bool isEmpty = useDecoder.getBool(Key.IS_EMPTY);
|
||||
mapLiterals.add(new MapLiteralUse(
|
||||
type, isConstant: isConstant, isEmpty: isEmpty));
|
||||
}
|
||||
}
|
||||
|
||||
return new DeserializedResolutionImpact(
|
||||
constSymbolNames: constSymbolNames,
|
||||
constantLiterals: constantLiterals,
|
||||
dynamicUses: dynamicUses,
|
||||
features: features,
|
||||
listLiterals: listLiterals,
|
||||
mapLiterals: mapLiterals,
|
||||
staticUses: staticUses,
|
||||
typeUses: typeUses);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ class Key {
|
|||
static const Key EXPORT_SCOPE = const Key('export-scope');
|
||||
static const Key EXPRESSION = const Key('expression');
|
||||
static const Key FALSE = const Key('false');
|
||||
static const Key FEATURES = const Key('features');
|
||||
static const Key FIELD = const Key('field');
|
||||
static const Key FIELDS = const Key('fields');
|
||||
static const Key FUNCTION = const Key('function');
|
||||
|
@ -42,6 +43,7 @@ class Key {
|
|||
static const Key IS_ABSTRACT = const Key('isAbstract');
|
||||
static const Key IS_CONST = const Key('isConst');
|
||||
static const Key IS_DEFERRED = const Key('isDeferred');
|
||||
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_NAMED = const Key('isNamed');
|
||||
|
@ -58,6 +60,8 @@ class Key {
|
|||
static const Key LIBRARY = const Key('library');
|
||||
static const Key LIBRARY_DEPENDENCY = const Key('library-dependency');
|
||||
static const Key LIBRARY_NAME = const Key('library-name');
|
||||
static const Key LISTS = const Key('lists');
|
||||
static const Key MAPS = const Key('maps');
|
||||
static const Key MEMBERS = const Key('members');
|
||||
static const Key MIXIN = const Key('mixin');
|
||||
static const Key MIXINS = const Key('mixins');
|
||||
|
@ -78,6 +82,7 @@ class Key {
|
|||
static const Key STATIC_USES = const Key('static-uses');
|
||||
static const Key SUPERTYPE = const Key('supertype');
|
||||
static const Key SUPERTYPES = const Key('supertypes');
|
||||
static const Key SYMBOLS = const Key('symbols');
|
||||
static const Key TAGS = const Key('tags');
|
||||
static const Key TRUE = const Key('true');
|
||||
static const Key TYPE = const Key('type');
|
||||
|
|
|
@ -7,6 +7,7 @@ library dart2js.serialization;
|
|||
import '../elements/elements.dart';
|
||||
import '../constants/expressions.dart';
|
||||
import '../dart_types.dart';
|
||||
import '../util/enumset.dart';
|
||||
|
||||
import 'constant_serialization.dart';
|
||||
import 'element_serialization.dart';
|
||||
|
@ -103,6 +104,17 @@ abstract class AbstractEncoder<K> {
|
|||
_map[key] = new EnumValue(value);
|
||||
}
|
||||
|
||||
/// Maps the [key] entry to the set of enum [values] in the encoded object.
|
||||
void setEnums(K key, Iterable values) {
|
||||
setEnumSet(key, new EnumSet.fromValues(values));
|
||||
}
|
||||
|
||||
/// Maps the [key] entry to the enum [set] in the encoded object.
|
||||
void setEnumSet(K key, EnumSet set) {
|
||||
_checkKey(key);
|
||||
_map[key] = new IntValue(set.value);
|
||||
}
|
||||
|
||||
/// Maps the [key] entry to the [element] in the encoded object.
|
||||
void setElement(K key, Element element) {
|
||||
_checkKey(key);
|
||||
|
@ -321,6 +333,22 @@ abstract class AbstractDecoder<K> {
|
|||
return enumValues[value];
|
||||
}
|
||||
|
||||
/// Returns the set of enum values associated with [key] in the decoded
|
||||
/// object.
|
||||
///
|
||||
/// If no value is associated with [key], then if [isOptional] is `true`,
|
||||
/// [defaultValue] is returned, otherwise an exception is thrown.
|
||||
EnumSet getEnums(K key, {bool isOptional: false}) {
|
||||
int value = _map[_getKeyValue(key)];
|
||||
if (value == null) {
|
||||
if (isOptional) {
|
||||
return const EnumSet.fixed(0);
|
||||
}
|
||||
throw new StateError("enum values '$key' not found in $_map.");
|
||||
}
|
||||
return new EnumSet.fixed(value);
|
||||
}
|
||||
|
||||
/// Returns the [Element] value associated with [key] in the decoded object.
|
||||
///
|
||||
/// If no value is associated with [key], then if [isOptional] is `true`,
|
||||
|
|
|
@ -8,6 +8,7 @@ import 'dart:async';
|
|||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:expect/expect.dart';
|
||||
import 'package:compiler/src/commandline_options.dart';
|
||||
import 'package:compiler/src/common/backend_api.dart';
|
||||
import 'package:compiler/src/common/names.dart';
|
||||
import 'package:compiler/src/common/resolution.dart';
|
||||
import 'package:compiler/src/compiler.dart';
|
||||
|
@ -247,7 +248,9 @@ Future analyze(String serializedData, Uri entryPoint, Test test) async {
|
|||
const JsonSerializationDecoder());
|
||||
deserializer.plugins.add(compiler.backend.serialization.deserializer);
|
||||
compiler.serialization.deserializer =
|
||||
new _DeserializerSystem(deserializer);
|
||||
new _DeserializerSystem(
|
||||
deserializer,
|
||||
compiler.backend.impactTransformer);
|
||||
});
|
||||
if (test != null) {
|
||||
Expect.equals(test.expectedErrorCount, diagnosticCollector.errors.length,
|
||||
|
@ -274,7 +277,7 @@ Future<String> serializeDartCore() async {
|
|||
String serialize(Compiler compiler) {
|
||||
Serializer serializer = new Serializer();
|
||||
serializer.plugins.add(compiler.backend.serialization.serializer);
|
||||
serializer.plugins.add(new WorldImpactSerializer(compiler.resolution));
|
||||
serializer.plugins.add(new ResolutionImpactSerializer(compiler.resolution));
|
||||
|
||||
for (LibraryElement library in compiler.libraryLoader.libraries) {
|
||||
serializer.serialize(library);
|
||||
|
@ -284,23 +287,23 @@ String serialize(Compiler compiler) {
|
|||
|
||||
const String WORLD_IMPACT_TAG = 'worldImpact';
|
||||
|
||||
class WorldImpactSerializer extends SerializerPlugin {
|
||||
class ResolutionImpactSerializer extends SerializerPlugin {
|
||||
final Resolution resolution;
|
||||
|
||||
WorldImpactSerializer(this.resolution);
|
||||
ResolutionImpactSerializer(this.resolution);
|
||||
|
||||
@override
|
||||
void onElement(Element element, ObjectEncoder createEncoder(String tag)) {
|
||||
if (resolution.hasBeenResolved(element)) {
|
||||
WorldImpact impact = resolution.getWorldImpact(element);
|
||||
ResolutionImpact impact = resolution.getResolutionImpact(element);
|
||||
ObjectEncoder encoder = createEncoder(WORLD_IMPACT_TAG);
|
||||
impact.apply(new ImpactSerializer(encoder));
|
||||
new ImpactSerializer(encoder).serialize(impact);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WorldImpactDeserializer extends DeserializerPlugin {
|
||||
Map<Element, WorldImpact> impactMap = <Element, WorldImpact>{};
|
||||
class ResolutionImpactDeserializer extends DeserializerPlugin {
|
||||
Map<Element, ResolutionImpact> impactMap = <Element, ResolutionImpact>{};
|
||||
|
||||
@override
|
||||
void onElement(Element element, ObjectDecoder getDecoder(String tag)) {
|
||||
|
@ -314,11 +317,12 @@ class WorldImpactDeserializer extends DeserializerPlugin {
|
|||
class _DeserializerSystem extends DeserializerSystem {
|
||||
final Deserializer _deserializer;
|
||||
final List<LibraryElement> deserializedLibraries = <LibraryElement>[];
|
||||
final WorldImpactDeserializer _worldImpactDeserializer =
|
||||
new WorldImpactDeserializer();
|
||||
final ResolutionImpactDeserializer _resolutionImpactDeserializer =
|
||||
new ResolutionImpactDeserializer();
|
||||
final ImpactTransformer _impactTransformer;
|
||||
|
||||
_DeserializerSystem(this._deserializer) {
|
||||
_deserializer.plugins.add(_worldImpactDeserializer);
|
||||
_DeserializerSystem(this._deserializer, this._impactTransformer) {
|
||||
_deserializer.plugins.add(_resolutionImpactDeserializer);
|
||||
}
|
||||
|
||||
LibraryElement readLibrary(Uri resolvedUri) {
|
||||
|
@ -331,12 +335,14 @@ class _DeserializerSystem extends DeserializerSystem {
|
|||
|
||||
@override
|
||||
WorldImpact computeWorldImpact(Element element) {
|
||||
WorldImpact impact = _worldImpactDeserializer.impactMap[element];
|
||||
if (impact == null) {
|
||||
ResolutionImpact resolutionImpact =
|
||||
_resolutionImpactDeserializer.impactMap[element];
|
||||
if (resolutionImpact == null) {
|
||||
print('No impact found for $element (${element.library})');
|
||||
impact = const WorldImpact();
|
||||
return const WorldImpact();
|
||||
} else {
|
||||
return _impactTransformer.transformResolutionImpact(resolutionImpact);
|
||||
}
|
||||
return impact;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
Loading…
Reference in a new issue