[dart2js] Support serialization of tree nodes in a known member context
* allows for a more compact encoding since every serialized
ir.TreeNode doesn't have to be prefixed by a references to its
surrounding member
* faster encoding since the surround member doesn't have to be found
for each serialized tree node
* better assertion message when trying to serialize an orphaned tree node
Change-Id: I1a5411d134a8c36c00b6f4164617bc0dce631009
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106088
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Stephen Adams <sra@google.com>
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 118d4ed..437ff2a 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -1336,7 +1336,8 @@
Map<ClassEntity, OutputUnit> classToUnit = source.readClassMap(() {
return outputUnits[source.readInt()];
});
- Map<MemberEntity, OutputUnit> memberToUnit = source.readMemberMap(() {
+ Map<MemberEntity, OutputUnit> memberToUnit =
+ source.readMemberMap((MemberEntity member) {
return outputUnits[source.readInt()];
});
Map<ConstantValue, OutputUnit> constantToUnit = source.readConstantMap(() {
@@ -1387,7 +1388,8 @@
sink.writeClassMap(_classToUnit, (OutputUnit outputUnit) {
sink.writeInt(outputUnitIndices[outputUnit]);
});
- sink.writeMemberMap(_memberToUnit, (OutputUnit outputUnit) {
+ sink.writeMemberMap(_memberToUnit,
+ (MemberEntity member, OutputUnit outputUnit) {
sink.writeInt(outputUnitIndices[outputUnit]);
});
sink.writeConstantMap(_constantToUnit, (OutputUnit outputUnit) {
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index 6266882..bf214c1 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -1433,49 +1433,59 @@
/// Deserializes a [GlobalTypeInferenceElementData] object from [source].
factory KernelGlobalTypeInferenceElementData.readFromDataSource(
- DataSource source, AbstractValueDomain abstractValueDomain) {
- source.begin(tag);
- Map<ir.TreeNode, AbstractValue> sendMap = source.readTreeNodeMap(
- () => abstractValueDomain.readAbstractValueFromDataSource(source),
- emptyAsNull: true);
- Map<ir.ForInStatement, AbstractValue> iteratorMap = source.readTreeNodeMap(
- () => abstractValueDomain.readAbstractValueFromDataSource(source),
- emptyAsNull: true);
- Map<ir.ForInStatement, AbstractValue> currentMap = source.readTreeNodeMap(
- () => abstractValueDomain.readAbstractValueFromDataSource(source),
- emptyAsNull: true);
- Map<ir.ForInStatement, AbstractValue> moveNextMap = source.readTreeNodeMap(
- () => abstractValueDomain.readAbstractValueFromDataSource(source),
- emptyAsNull: true);
- source.end(tag);
- return new KernelGlobalTypeInferenceElementData.internal(
- sendMap, iteratorMap, currentMap, moveNextMap);
+ DataSource source,
+ ir.Member context,
+ AbstractValueDomain abstractValueDomain) {
+ return source.inMemberContext(context, () {
+ source.begin(tag);
+ Map<ir.TreeNode, AbstractValue> sendMap = source.readTreeNodeMapInContext(
+ () => abstractValueDomain.readAbstractValueFromDataSource(source),
+ emptyAsNull: true);
+ Map<ir.ForInStatement, AbstractValue> iteratorMap =
+ source.readTreeNodeMapInContext(
+ () => abstractValueDomain.readAbstractValueFromDataSource(source),
+ emptyAsNull: true);
+ Map<ir.ForInStatement, AbstractValue> currentMap =
+ source.readTreeNodeMapInContext(
+ () => abstractValueDomain.readAbstractValueFromDataSource(source),
+ emptyAsNull: true);
+ Map<ir.ForInStatement, AbstractValue> moveNextMap =
+ source.readTreeNodeMapInContext(
+ () => abstractValueDomain.readAbstractValueFromDataSource(source),
+ emptyAsNull: true);
+ source.end(tag);
+ return new KernelGlobalTypeInferenceElementData.internal(
+ sendMap, iteratorMap, currentMap, moveNextMap);
+ });
}
@override
- void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
- sink.begin(tag);
- sink.writeTreeNodeMap(
- _sendMap,
- (AbstractValue value) =>
- abstractValueDomain.writeAbstractValueToDataSink(sink, value),
- allowNull: true);
- sink.writeTreeNodeMap(
- _iteratorMap,
- (AbstractValue value) =>
- abstractValueDomain.writeAbstractValueToDataSink(sink, value),
- allowNull: true);
- sink.writeTreeNodeMap(
- _currentMap,
- (AbstractValue value) =>
- abstractValueDomain.writeAbstractValueToDataSink(sink, value),
- allowNull: true);
- sink.writeTreeNodeMap(
- _moveNextMap,
- (AbstractValue value) =>
- abstractValueDomain.writeAbstractValueToDataSink(sink, value),
- allowNull: true);
- sink.end(tag);
+ void writeToDataSink(DataSink sink, ir.Member context,
+ AbstractValueDomain abstractValueDomain) {
+ sink.inMemberContext(context, () {
+ sink.begin(tag);
+ sink.writeTreeNodeMapInContext(
+ _sendMap,
+ (AbstractValue value) =>
+ abstractValueDomain.writeAbstractValueToDataSink(sink, value),
+ allowNull: true);
+ sink.writeTreeNodeMapInContext(
+ _iteratorMap,
+ (AbstractValue value) =>
+ abstractValueDomain.writeAbstractValueToDataSink(sink, value),
+ allowNull: true);
+ sink.writeTreeNodeMapInContext(
+ _currentMap,
+ (AbstractValue value) =>
+ abstractValueDomain.writeAbstractValueToDataSink(sink, value),
+ allowNull: true);
+ sink.writeTreeNodeMapInContext(
+ _moveNextMap,
+ (AbstractValue value) =>
+ abstractValueDomain.writeAbstractValueToDataSink(sink, value),
+ allowNull: true);
+ sink.end(tag);
+ });
}
@override
diff --git a/pkg/compiler/lib/src/inferrer/types.dart b/pkg/compiler/lib/src/inferrer/types.dart
index f68b519..374f01a 100644
--- a/pkg/compiler/lib/src/inferrer/types.dart
+++ b/pkg/compiler/lib/src/inferrer/types.dart
@@ -11,6 +11,7 @@
import '../compiler.dart' show Compiler;
import '../elements/entities.dart';
import '../js_backend/inferred_data.dart';
+import '../js_model/element_map.dart';
import '../inferrer/type_graph_inferrer.dart' show TypeGraphInferrer;
import '../serialization/serialization.dart';
import '../universe/selector.dart' show Selector;
@@ -30,12 +31,13 @@
/// based queries (the runtime value could be anything).
abstract class GlobalTypeInferenceMemberResult {
/// Deserializes a [GlobalTypeInferenceMemberResult] object from [source].
- factory GlobalTypeInferenceMemberResult.readFromDataSource(
- DataSource source, AbstractValueDomain abstractValueDomain) =
+ factory GlobalTypeInferenceMemberResult.readFromDataSource(DataSource source,
+ ir.Member context, AbstractValueDomain abstractValueDomain) =
GlobalTypeInferenceMemberResultImpl.readFromDataSource;
/// Serializes this [GlobalTypeInferenceMemberResult] to [sink].
- void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain);
+ void writeToDataSink(DataSink sink, ir.Member context,
+ AbstractValueDomain abstractValueDomain);
/// The inferred type when this result belongs to a field, null otherwise.
AbstractValue get type;
@@ -72,12 +74,13 @@
/// a single element.
abstract class GlobalTypeInferenceElementData {
/// Deserializes a [GlobalTypeInferenceElementData] object from [source].
- factory GlobalTypeInferenceElementData.readFromDataSource(
- DataSource source, AbstractValueDomain abstractValueDomain) =
+ factory GlobalTypeInferenceElementData.readFromDataSource(DataSource source,
+ ir.Member context, AbstractValueDomain abstractValueDomain) =
KernelGlobalTypeInferenceElementData.readFromDataSource;
/// Serializes this [GlobalTypeInferenceElementData] to [sink].
- void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain);
+ void writeToDataSink(DataSink sink, ir.Member context,
+ AbstractValueDomain abstractValueDomain);
/// Compresses the inner representation by removing [AbstractValue] mappings
/// to `null`. Returns the data object itself or `null` if the data object
@@ -109,17 +112,20 @@
abstract class GlobalTypeInferenceResults {
/// Deserializes a [GlobalTypeInferenceResults] object from [source].
factory GlobalTypeInferenceResults.readFromDataSource(
- DataSource source, JClosedWorld closedWorld, InferredData inferredData) {
+ DataSource source,
+ JsToElementMap elementMap,
+ JClosedWorld closedWorld,
+ InferredData inferredData) {
bool isTrivial = source.readBool();
if (isTrivial) {
return new TrivialGlobalTypeInferenceResults(closedWorld);
}
return new GlobalTypeInferenceResultsImpl.readFromDataSource(
- source, closedWorld, inferredData);
+ source, elementMap, closedWorld, inferredData);
}
/// Serializes this [GlobalTypeInferenceResults] to [sink].
- void writeToDataSink(DataSink sink);
+ void writeToDataSink(DataSink sink, JsToElementMap elementMap);
JClosedWorld get closedWorld;
@@ -217,12 +223,17 @@
_trivialParameterResult = closedWorld.abstractValueDomain.dynamicType;
factory GlobalTypeInferenceResultsImpl.readFromDataSource(
- DataSource source, JClosedWorld closedWorld, InferredData inferredData) {
+ DataSource source,
+ JsToElementMap elementMap,
+ JClosedWorld closedWorld,
+ InferredData inferredData) {
source.begin(tag);
Map<MemberEntity, GlobalTypeInferenceMemberResult> memberResults =
- source.readMemberMap(() =>
+ source.readMemberMap((MemberEntity member) =>
new GlobalTypeInferenceMemberResult.readFromDataSource(
- source, closedWorld.abstractValueDomain));
+ source,
+ elementMap.getMemberContextNode(member),
+ closedWorld.abstractValueDomain));
Map<Local, AbstractValue> parameterResults = source.readLocalMap(() =>
closedWorld.abstractValueDomain
.readAbstractValueFromDataSource(source));
@@ -244,13 +255,16 @@
}
@override
- void writeToDataSink(DataSink sink) {
+ void writeToDataSink(DataSink sink, JsToElementMap elementMap) {
sink.writeBool(false); // Is _not_ trivial.
sink.begin(tag);
sink.writeMemberMap(
memberResults,
- (GlobalTypeInferenceMemberResult result) =>
- result.writeToDataSink(sink, closedWorld.abstractValueDomain));
+ (MemberEntity member, GlobalTypeInferenceMemberResult result) =>
+ result.writeToDataSink(
+ sink,
+ elementMap.getMemberContextNode(member),
+ closedWorld.abstractValueDomain));
sink.writeLocalMap(
parameterResults,
(AbstractValue value) => closedWorld.abstractValueDomain
@@ -395,11 +409,13 @@
{this.throwsAlways, this.isCalledOnce});
factory GlobalTypeInferenceMemberResultImpl.readFromDataSource(
- DataSource source, AbstractValueDomain abstractValueDomain) {
+ DataSource source,
+ ir.Member context,
+ AbstractValueDomain abstractValueDomain) {
source.begin(tag);
GlobalTypeInferenceElementData data = source.readValueOrNull(() {
return new GlobalTypeInferenceElementData.readFromDataSource(
- source, abstractValueDomain);
+ source, context, abstractValueDomain);
});
AbstractValue returnType =
abstractValueDomain.readAbstractValueFromDataSource(source);
@@ -413,10 +429,11 @@
}
@override
- void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
+ void writeToDataSink(DataSink sink, ir.Member context,
+ AbstractValueDomain abstractValueDomain) {
sink.begin(tag);
sink.writeValueOrNull(_data, (GlobalTypeInferenceElementData data) {
- data.writeToDataSink(sink, abstractValueDomain);
+ data.writeToDataSink(sink, context, abstractValueDomain);
});
abstractValueDomain.writeAbstractValueToDataSink(sink, returnType);
abstractValueDomain.writeAbstractValueToDataSink(sink, type);
@@ -453,7 +470,7 @@
_trivialParameterResult = closedWorld.abstractValueDomain.dynamicType;
@override
- void writeToDataSink(DataSink sink) {
+ void writeToDataSink(DataSink sink, JsToElementMap elementMap) {
sink.writeBool(true); // Is trivial.
}
@@ -516,7 +533,8 @@
bool get isCalledOnce => false;
@override
- void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
+ void writeToDataSink(DataSink sink, ir.Member context,
+ AbstractValueDomain abstractValueDomain) {
throw new UnsupportedError(
"TrivialGlobalTypeInferenceMemberResult.writeToDataSink");
}
@@ -559,7 +577,8 @@
bool get isCalledOnce => false;
@override
- void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
+ void writeToDataSink(DataSink sink, ir.Member context,
+ AbstractValueDomain abstractValueDomain) {
throw new UnsupportedError(
"DeadFieldGlobalTypeInferenceResult.writeToDataSink");
}
@@ -602,7 +621,8 @@
bool get isCalledOnce => false;
@override
- void writeToDataSink(DataSink sink, AbstractValueDomain abstractValueDomain) {
+ void writeToDataSink(DataSink sink, ir.Member context,
+ AbstractValueDomain abstractValueDomain) {
throw new UnsupportedError(
"DeadFieldGlobalTypeInferenceResult.writeToDataSink");
}
diff --git a/pkg/compiler/lib/src/ir/impact_data.dart b/pkg/compiler/lib/src/ir/impact_data.dart
index 79a7960..7276ae4 100644
--- a/pkg/compiler/lib/src/ir/impact_data.dart
+++ b/pkg/compiler/lib/src/ir/impact_data.dart
@@ -574,7 +574,7 @@
emptyAsNull: true);
_fieldInitializers = source.readMemberNodes(emptyAsNull: true);
_fieldConstantInitializers =
- source.readMemberMap(() => source.readTreeNodes(), emptyAsNull: true);
+ source.readMemberNodeMap(source.readTreeNodes, emptyAsNull: true);
_typeLiterals = source.readList(
() => new _TypeLiteral.fromDataSource(source),
emptyAsNull: true);
diff --git a/pkg/compiler/lib/src/ir/static_type_cache.dart b/pkg/compiler/lib/src/ir/static_type_cache.dart
index 64cf6b8..2e25d65 100644
--- a/pkg/compiler/lib/src/ir/static_type_cache.dart
+++ b/pkg/compiler/lib/src/ir/static_type_cache.dart
@@ -19,22 +19,28 @@
const StaticTypeCache(
[this._expressionTypes = const {}, this._forInIteratorTypes]);
- factory StaticTypeCache.readFromDataSource(DataSource source) {
- source.begin(tag);
- Map<ir.Expression, ir.DartType> expressionTypes =
- source.readTreeNodeMap(source.readDartTypeNode);
- Map<ir.ForInStatement, ir.DartType> forInIteratorTypes =
- source.readTreeNodeMap(source.readDartTypeNode, emptyAsNull: true);
- source.end(tag);
- return new StaticTypeCache(expressionTypes, forInIteratorTypes);
+ factory StaticTypeCache.readFromDataSource(
+ DataSource source, ir.Member context) {
+ return source.inMemberContext(context, () {
+ source.begin(tag);
+ Map<ir.Expression, ir.DartType> expressionTypes =
+ source.readTreeNodeMapInContext(source.readDartTypeNode);
+ Map<ir.ForInStatement, ir.DartType> forInIteratorTypes = source
+ .readTreeNodeMapInContext(source.readDartTypeNode, emptyAsNull: true);
+ source.end(tag);
+ return new StaticTypeCache(expressionTypes, forInIteratorTypes);
+ });
}
- void writeToDataSink(DataSink sink) {
- sink.begin(tag);
- sink.writeTreeNodeMap(_expressionTypes, sink.writeDartTypeNode);
- sink.writeTreeNodeMap(_forInIteratorTypes, sink.writeDartTypeNode,
- allowNull: true);
- sink.end(tag);
+ void writeToDataSink(DataSink sink, ir.Member context) {
+ sink.inMemberContext(context, () {
+ sink.begin(tag);
+ sink.writeTreeNodeMapInContext(_expressionTypes, sink.writeDartTypeNode);
+ sink.writeTreeNodeMapInContext(
+ _forInIteratorTypes, sink.writeDartTypeNode,
+ allowNull: true);
+ sink.end(tag);
+ });
}
ir.DartType operator [](ir.Expression node) => _expressionTypes[node];
diff --git a/pkg/compiler/lib/src/js_backend/annotations.dart b/pkg/compiler/lib/src/js_backend/annotations.dart
index 1464c0b..97678ca 100644
--- a/pkg/compiler/lib/src/js_backend/annotations.dart
+++ b/pkg/compiler/lib/src/js_backend/annotations.dart
@@ -268,7 +268,8 @@
factory AnnotationsDataImpl.readFromDataSource(DataSource source) {
source.begin(tag);
Map<MemberEntity, EnumSet<PragmaAnnotation>> pragmaAnnotations =
- source.readMemberMap(() => new EnumSet.fromValue(source.readInt()));
+ source.readMemberMap(
+ (MemberEntity member) => new EnumSet.fromValue(source.readInt()));
source.end(tag);
return new AnnotationsDataImpl(pragmaAnnotations);
}
@@ -276,7 +277,8 @@
@override
void writeToDataSink(DataSink sink) {
sink.begin(tag);
- sink.writeMemberMap(pragmaAnnotations, (EnumSet<PragmaAnnotation> set) {
+ sink.writeMemberMap(pragmaAnnotations,
+ (MemberEntity member, EnumSet<PragmaAnnotation> set) {
sink.writeInt(set.value);
});
sink.end(tag);
diff --git a/pkg/compiler/lib/src/js_backend/field_analysis.dart b/pkg/compiler/lib/src/js_backend/field_analysis.dart
index 77aa43e..aa2c328 100644
--- a/pkg/compiler/lib/src/js_backend/field_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/field_analysis.dart
@@ -235,8 +235,8 @@
factory JFieldAnalysis.readFromDataSource(
DataSource source, CompilerOptions options) {
source.begin(tag);
- Map<FieldEntity, FieldAnalysisData> fieldData = source
- .readMemberMap(() => new FieldAnalysisData.fromDataSource(source));
+ Map<FieldEntity, FieldAnalysisData> fieldData = source.readMemberMap(
+ (MemberEntity member) => new FieldAnalysisData.fromDataSource(source));
source.end(tag);
return new JFieldAnalysis._(fieldData);
}
@@ -245,7 +245,9 @@
void writeToDataSink(DataSink sink) {
sink.begin(tag);
sink.writeMemberMap(
- _fieldData, (FieldAnalysisData data) => data.writeToDataSink(sink));
+ _fieldData,
+ (MemberEntity member, FieldAnalysisData data) =>
+ data.writeToDataSink(sink));
sink.end(tag);
}
diff --git a/pkg/compiler/lib/src/js_backend/inferred_data.dart b/pkg/compiler/lib/src/js_backend/inferred_data.dart
index be9b3dc..b84035c 100644
--- a/pkg/compiler/lib/src/js_backend/inferred_data.dart
+++ b/pkg/compiler/lib/src/js_backend/inferred_data.dart
@@ -103,8 +103,8 @@
DataSource source, JClosedWorld closedWorld) {
source.begin(tag);
Set<MemberEntity> functionsCalledInLoop = source.readMembers().toSet();
- Map<FunctionEntity, SideEffects> sideEffects =
- source.readMemberMap(() => new SideEffects.readFromDataSource(source));
+ Map<FunctionEntity, SideEffects> sideEffects = source.readMemberMap(
+ (MemberEntity member) => new SideEffects.readFromDataSource(source));
Set<FunctionEntity> sideEffectsFreeElements =
source.readMembers<FunctionEntity>().toSet();
Set<FunctionEntity> elementsThatCannotThrow =
@@ -126,8 +126,10 @@
sink.writeBool(false); // Is _not_ trivial.
sink.begin(tag);
sink.writeMembers(_functionsCalledInLoop);
- sink.writeMemberMap(_sideEffects,
- (SideEffects sideEffects) => sideEffects.writeToDataSink(sink));
+ sink.writeMemberMap(
+ _sideEffects,
+ (MemberEntity member, SideEffects sideEffects) =>
+ sideEffects.writeToDataSink(sink));
sink.writeMembers(_sideEffectsFreeElements);
sink.writeMembers(_elementsThatCannotThrow);
sink.writeMembers(_functionsThatMightBePassedToApply);
diff --git a/pkg/compiler/lib/src/js_backend/native_data.dart b/pkg/compiler/lib/src/js_backend/native_data.dart
index 3342b54..cc517d2 100644
--- a/pkg/compiler/lib/src/js_backend/native_data.dart
+++ b/pkg/compiler/lib/src/js_backend/native_data.dart
@@ -348,7 +348,7 @@
source.readClassMap(source.readString);
Set<ClassEntity> anonymousJsInteropClasses = source.readClasses().toSet();
Map<MemberEntity, String> jsInteropMembers =
- source.readMemberMap(source.readString);
+ source.readMemberMap((MemberEntity member) => source.readString());
source.end(tag);
return new NativeBasicDataImpl(
elementEnvironment,
@@ -369,7 +369,8 @@
sink.writeLibraryMap(jsInteropLibraries, sink.writeString);
sink.writeClassMap(jsInteropClasses, sink.writeString);
sink.writeClasses(anonymousJsInteropClasses);
- sink.writeMemberMap(jsInteropMembers, sink.writeString);
+ sink.writeMemberMap(jsInteropMembers,
+ (MemberEntity member, String name) => sink.writeString(name));
sink.end(tag);
}
@@ -576,13 +577,16 @@
NativeBasicData nativeBasicData =
new NativeBasicData.readFromDataSource(source, elementEnvironment);
Map<MemberEntity, String> nativeMemberName =
- source.readMemberMap(source.readString);
- Map<FunctionEntity, NativeBehavior> nativeMethodBehavior = source
- .readMemberMap(() => new NativeBehavior.readFromDataSource(source));
- Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior = source
- .readMemberMap(() => new NativeBehavior.readFromDataSource(source));
- Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior = source
- .readMemberMap(() => new NativeBehavior.readFromDataSource(source));
+ source.readMemberMap((MemberEntity member) => source.readString());
+ Map<FunctionEntity, NativeBehavior> nativeMethodBehavior =
+ source.readMemberMap((MemberEntity member) =>
+ new NativeBehavior.readFromDataSource(source));
+ Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior =
+ source.readMemberMap((MemberEntity member) =>
+ new NativeBehavior.readFromDataSource(source));
+ Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior =
+ source.readMemberMap((MemberEntity member) =>
+ new NativeBehavior.readFromDataSource(source));
source.end(tag);
return new NativeDataImpl(
nativeBasicData,
@@ -597,16 +601,20 @@
sink.begin(tag);
_nativeBasicData.writeToDataSink(sink);
- sink.writeMemberMap(nativeMemberName, sink.writeString);
+ sink.writeMemberMap(nativeMemberName,
+ (MemberEntity member, String name) => sink.writeString(name));
- sink.writeMemberMap(nativeMethodBehavior, (NativeBehavior behavior) {
+ sink.writeMemberMap(nativeMethodBehavior,
+ (MemberEntity member, NativeBehavior behavior) {
behavior.writeToDataSink(sink);
});
- sink.writeMemberMap(nativeFieldLoadBehavior, (NativeBehavior behavior) {
+ sink.writeMemberMap(nativeFieldLoadBehavior,
+ (MemberEntity member, NativeBehavior behavior) {
behavior.writeToDataSink(sink);
});
- sink.writeMemberMap(nativeFieldStoreBehavior, (NativeBehavior behavior) {
+ sink.writeMemberMap(nativeFieldStoreBehavior,
+ (MemberEntity member, NativeBehavior behavior) {
behavior.writeToDataSink(sink);
});
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index 2ee5d5c..32f7f78 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -49,12 +49,13 @@
JsToElementMap elementMap, DataSource source) {
source.begin(tag);
// TODO(johnniwinther): Support shared [ScopeInfo].
- Map<MemberEntity, ScopeInfo> scopeMap =
- source.readMemberMap(() => new ScopeInfo.readFromDataSource(source));
+ Map<MemberEntity, ScopeInfo> scopeMap = source.readMemberMap(
+ (MemberEntity member) => new ScopeInfo.readFromDataSource(source));
Map<ir.TreeNode, CapturedScope> capturedScopesMap = source
.readTreeNodeMap(() => new CapturedScope.readFromDataSource(source));
- Map<MemberEntity, CapturedScope> capturedScopeForSignatureMap = source
- .readMemberMap(() => new CapturedScope.readFromDataSource(source));
+ Map<MemberEntity, CapturedScope> capturedScopeForSignatureMap =
+ source.readMemberMap((MemberEntity member) =>
+ new CapturedScope.readFromDataSource(source));
Map<ir.LocalFunction, ClosureRepresentationInfo>
localClosureRepresentationMap = source.readTreeNodeMap(
() => new ClosureRepresentationInfo.readFromDataSource(source));
@@ -67,13 +68,15 @@
@override
void writeToDataSink(DataSink sink) {
sink.begin(tag);
- sink.writeMemberMap(
- _scopeMap, (ScopeInfo info) => info.writeToDataSink(sink));
+ sink.writeMemberMap(_scopeMap,
+ (MemberEntity member, ScopeInfo info) => info.writeToDataSink(sink));
sink.writeTreeNodeMap(_capturedScopesMap, (CapturedScope scope) {
scope.writeToDataSink(sink);
});
- sink.writeMemberMap(_capturedScopeForSignatureMap,
- (CapturedScope scope) => scope.writeToDataSink(sink));
+ sink.writeMemberMap(
+ _capturedScopeForSignatureMap,
+ (MemberEntity member, CapturedScope scope) =>
+ scope.writeToDataSink(sink));
sink.writeTreeNodeMap(_localClosureRepresentationMap,
(ClosureRepresentationInfo info) {
info.writeToDataSink(sink);
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index 3fb71a4..0a88fbe 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -120,11 +120,14 @@
List<DartType> getDartTypes(List<ir.DartType> types);
/// Returns the definition information for [member].
- MemberDefinition getMemberDefinition(covariant MemberEntity member);
+ MemberDefinition getMemberDefinition(MemberEntity member);
+
+ /// Returns the [ir.Member] containing the definition of [member], if any.
+ ir.Member getMemberContextNode(MemberEntity member);
/// Returns the type of `this` in [member], or `null` if member is defined in
/// a static context.
- InterfaceType getMemberThisType(covariant MemberEntity member);
+ InterfaceType getMemberThisType(MemberEntity member);
/// Returns how [member] has access to type variables of the this type
/// returned by [getMemberThisType].
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index e24352c..15e56a5 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -437,8 +437,8 @@
source.end(typeVariableDataTag);
source.begin(nestedClosuresTag);
- _nestedClosureMap.addAll(
- source.readMemberMap(() => source.readMembers<IndexedFunction>()));
+ _nestedClosureMap.addAll(source.readMemberMap(
+ (MemberEntity member) => source.readMembers<IndexedFunction>()));
source.end(nestedClosuresTag);
source.end(tag);
@@ -548,7 +548,10 @@
sink.end(typeVariableDataTag);
sink.begin(nestedClosuresTag);
- sink.writeMemberMap(_nestedClosureMap, sink.writeMembers);
+ sink.writeMemberMap(
+ _nestedClosureMap,
+ (MemberEntity member, List<IndexedFunction> functions) =>
+ sink.writeMembers(functions));
sink.end(nestedClosuresTag);
sink.end(tag);
@@ -1673,6 +1676,33 @@
}
@override
+ ir.Member getMemberContextNode(MemberEntity member) {
+ ir.Member getParentMember(ir.TreeNode node) {
+ while (node != null) {
+ if (node is ir.Member) {
+ return node;
+ }
+ node = node.parent;
+ }
+ return null;
+ }
+
+ MemberDefinition definition = getMemberDefinition(member);
+ switch (definition.kind) {
+ case MemberKind.regular:
+ case MemberKind.constructor:
+ case MemberKind.constructorBody:
+ return definition.node;
+ case MemberKind.closureCall:
+ case MemberKind.closureField:
+ case MemberKind.signature:
+ case MemberKind.generatorBody:
+ return getParentMember(definition.node);
+ }
+ throw new UnsupportedError('Unexpected member kind ${definition}');
+ }
+
+ @override
ClassDefinition getClassDefinition(ClassEntity cls) {
return getClassDefinitionInternal(cls);
}
diff --git a/pkg/compiler/lib/src/js_model/env.dart b/pkg/compiler/lib/src/js_model/env.dart
index 9017330..ac096b1 100644
--- a/pkg/compiler/lib/src/js_model/env.dart
+++ b/pkg/compiler/lib/src/js_model/env.dart
@@ -678,7 +678,7 @@
MemberDefinition definition =
new MemberDefinition.readFromDataSource(source);
StaticTypeCache staticTypes =
- new StaticTypeCache.readFromDataSource(source);
+ new StaticTypeCache.readFromDataSource(source, node);
source.end(tag);
return new FunctionDataImpl(node, functionNode, definition, staticTypes);
}
@@ -689,7 +689,7 @@
sink.begin(tag);
sink.writeMemberNode(node);
definition.writeToDataSink(sink);
- staticTypes.writeToDataSink(sink);
+ staticTypes.writeToDataSink(sink, node);
sink.end(tag);
}
@@ -877,7 +877,7 @@
MemberDefinition definition =
new MemberDefinition.readFromDataSource(source);
StaticTypeCache staticTypes =
- new StaticTypeCache.readFromDataSource(source);
+ new StaticTypeCache.readFromDataSource(source, node);
source.end(tag);
return new JConstructorDataImpl(
node, functionNode, definition, staticTypes);
@@ -890,7 +890,7 @@
sink.writeMemberNode(node);
definition.writeToDataSink(sink);
assert(constructorBody == null);
- staticTypes.writeToDataSink(sink);
+ staticTypes.writeToDataSink(sink, node);
sink.end(tag);
}
@@ -940,7 +940,7 @@
MemberDefinition definition =
new MemberDefinition.readFromDataSource(source);
StaticTypeCache staticTypes =
- new StaticTypeCache.readFromDataSource(source);
+ new StaticTypeCache.readFromDataSource(source, node);
source.end(tag);
return new ConstructorBodyDataImpl(
node, functionNode, definition, staticTypes);
@@ -952,7 +952,7 @@
sink.begin(tag);
sink.writeMemberNode(node);
definition.writeToDataSink(sink);
- staticTypes.writeToDataSink(sink);
+ staticTypes.writeToDataSink(sink, node);
sink.end(tag);
}
@@ -988,7 +988,7 @@
MemberDefinition definition =
new MemberDefinition.readFromDataSource(source);
StaticTypeCache staticTypes =
- new StaticTypeCache.readFromDataSource(source);
+ new StaticTypeCache.readFromDataSource(source, node);
source.end(tag);
return new JFieldDataImpl(node, definition, staticTypes);
}
@@ -999,7 +999,7 @@
sink.begin(tag);
sink.writeMemberNode(node);
definition.writeToDataSink(sink);
- staticTypes.writeToDataSink(sink);
+ staticTypes.writeToDataSink(sink, node);
sink.end(tag);
}
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index 3515770..b1beeb8 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -173,8 +173,8 @@
elementMap.lateOutputUnitDataBuilder =
new LateOutputUnitDataBuilder(outputUnitData);
- Map<MemberEntity, MemberAccess> memberAccess =
- source.readMemberMap(() => new MemberAccess.readFromDataSource(source));
+ Map<MemberEntity, MemberAccess> memberAccess = source.readMemberMap(
+ (MemberEntity member) => new MemberAccess.readFromDataSource(source));
source.end(tag);
@@ -228,7 +228,9 @@
closureDataLookup.writeToDataSink(sink);
outputUnitData.writeToDataSink(sink);
sink.writeMemberMap(
- memberAccess, (MemberAccess access) => access.writeToDataSink(sink));
+ memberAccess,
+ (MemberEntity member, MemberAccess access) =>
+ access.writeToDataSink(sink));
sink.end(tag);
}
diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart
index a1af8e8..484d24f 100644
--- a/pkg/compiler/lib/src/serialization/abstract_sink.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart
@@ -39,6 +39,9 @@
final Map<String, int> tagFrequencyMap;
+ ir.Member _currentMemberContext;
+ _MemberData _currentMemberData;
+
AbstractDataSink({this.useDataKinds: false, this.tagFrequencyMap}) {
_dartTypeWriter = new DartTypeWriter(this);
_dartTypeNodeWriter = new DartTypeNodeWriter(this);
@@ -73,6 +76,24 @@
}
@override
+ void inMemberContext(ir.Member context, void f()) {
+ ir.Member oldMemberContext = _currentMemberContext;
+ _MemberData oldMemberData = _currentMemberData;
+ _currentMemberContext = context;
+ _currentMemberData = null;
+ f();
+ _currentMemberData = oldMemberData;
+ _currentMemberContext = oldMemberContext;
+ }
+
+ _MemberData get currentMemberData {
+ assert(_currentMemberContext != null,
+ "DataSink has no current member context.");
+ return _currentMemberData ??= _memberData[_currentMemberContext] ??=
+ new _MemberData(_currentMemberContext);
+ }
+
+ @override
void writeCached<E>(E value, void f(E value)) {
IndexedSink sink = _generalCaches[E] ??= new IndexedSink<E>(this);
sink.write(value, (v) => f(v));
@@ -221,10 +242,58 @@
@override
void writeTreeNode(ir.TreeNode value) {
_writeDataKind(DataKind.treeNode);
- _writeTreeNode(value);
+ _writeTreeNode(value, null);
}
- void _writeTreeNode(ir.TreeNode value) {
+ @override
+ void writeTreeNodeInContext(ir.TreeNode value) {
+ writeTreeNodeInContextInternal(value, currentMemberData);
+ }
+
+ void writeTreeNodeInContextInternal(
+ ir.TreeNode value, _MemberData memberData) {
+ _writeDataKind(DataKind.treeNode);
+ _writeTreeNode(value, memberData);
+ }
+
+ @override
+ void writeTreeNodeOrNullInContext(ir.TreeNode value) {
+ writeBool(value != null);
+ if (value != null) {
+ writeTreeNodeInContextInternal(value, currentMemberData);
+ }
+ }
+
+ @override
+ void writeTreeNodesInContext(Iterable<ir.TreeNode> values,
+ {bool allowNull: false}) {
+ if (values == null) {
+ assert(allowNull);
+ writeInt(0);
+ } else {
+ writeInt(values.length);
+ for (ir.TreeNode value in values) {
+ writeTreeNodeInContextInternal(value, currentMemberData);
+ }
+ }
+ }
+
+ @override
+ void writeTreeNodeMapInContext<V>(Map<ir.TreeNode, V> map, void f(V value),
+ {bool allowNull: false}) {
+ if (map == null) {
+ assert(allowNull);
+ writeInt(0);
+ } else {
+ writeInt(map.length);
+ map.forEach((ir.TreeNode key, V value) {
+ writeTreeNodeInContextInternal(key, currentMemberData);
+ f(value);
+ });
+ }
+ }
+
+ void _writeTreeNode(ir.TreeNode value, _MemberData memberData) {
if (value is ir.Class) {
_writeEnumInternal(_TreeNodeKind.cls);
_writeClassNode(value);
@@ -234,39 +303,43 @@
} else if (value is ir.VariableDeclaration &&
value.parent is ir.FunctionDeclaration) {
_writeEnumInternal(_TreeNodeKind.functionDeclarationVariable);
- _writeTreeNode(value.parent);
+ _writeTreeNode(value.parent, memberData);
} else if (value is ir.FunctionNode) {
_writeEnumInternal(_TreeNodeKind.functionNode);
- _writeFunctionNode(value);
+ _writeFunctionNode(value, memberData);
} else if (value is ir.TypeParameter) {
_writeEnumInternal(_TreeNodeKind.typeParameter);
- _writeTypeParameter(value);
+ _writeTypeParameter(value, memberData);
} else if (value is ConstantReference) {
_writeEnumInternal(_TreeNodeKind.constant);
- _writeTreeNode(value.expression);
+ _writeTreeNode(value.expression, memberData);
_ConstantNodeIndexerVisitor indexer = new _ConstantNodeIndexerVisitor();
value.expression.constant.accept(indexer);
_writeIntInternal(indexer.getIndex(value.constant));
} else {
_writeEnumInternal(_TreeNodeKind.node);
- ir.TreeNode member = value;
- while (member is! ir.Member) {
- if (member == null) {
- throw new UnsupportedError("No enclosing member of TreeNode "
- "$value (${value.runtimeType})");
+ if (memberData == null) {
+ ir.TreeNode member = value;
+ while (member is! ir.Member) {
+ if (member == null) {
+ throw new UnsupportedError("No enclosing member of TreeNode "
+ "$value (${value.runtimeType})");
+ }
+ member = member.parent;
}
- member = member.parent;
+ _writeMemberNode(member);
+ memberData = _memberData[member] ??= new _MemberData(member);
}
- _writeMemberNode(member);
- _MemberData memberData = _memberData[member] ??= new _MemberData(member);
int index = memberData.getIndexByTreeNode(value);
assert(
- index != null, "No TreeNode index found for ${value.runtimeType}.");
+ index != null,
+ "No TreeNode index found for ${value.runtimeType} "
+ "found in ${memberData}.");
_writeIntInternal(index);
}
}
- void _writeFunctionNode(ir.FunctionNode value) {
+ void _writeFunctionNode(ir.FunctionNode value, _MemberData memberData) {
ir.TreeNode parent = value.parent;
if (parent is ir.Procedure) {
_writeEnumInternal(_FunctionNodeKind.procedure);
@@ -276,10 +349,10 @@
_writeMemberNode(parent);
} else if (parent is ir.FunctionExpression) {
_writeEnumInternal(_FunctionNodeKind.functionExpression);
- _writeTreeNode(parent);
+ _writeTreeNode(parent, memberData);
} else if (parent is ir.FunctionDeclaration) {
_writeEnumInternal(_FunctionNodeKind.functionDeclaration);
- _writeTreeNode(parent);
+ _writeTreeNode(parent, memberData);
} else {
throw new UnsupportedError(
"Unsupported FunctionNode parent ${parent.runtimeType}");
@@ -289,10 +362,10 @@
@override
void writeTypeParameterNode(ir.TypeParameter value) {
_writeDataKind(DataKind.typeParameterNode);
- _writeTypeParameter(value);
+ _writeTypeParameter(value, null);
}
- void _writeTypeParameter(ir.TypeParameter value) {
+ void _writeTypeParameter(ir.TypeParameter value, _MemberData memberData) {
ir.TreeNode parent = value.parent;
if (parent is ir.Class) {
_writeEnumInternal(_TypeParameterKind.cls);
@@ -300,7 +373,7 @@
_writeIntInternal(parent.typeParameters.indexOf(value));
} else if (parent is ir.FunctionNode) {
_writeEnumInternal(_TypeParameterKind.functionNode);
- _writeFunctionNode(parent);
+ _writeFunctionNode(parent, memberData);
_writeIntInternal(parent.typeParameters.indexOf(value));
} else {
throw new UnsupportedError(
@@ -438,7 +511,8 @@
case ConstantValueKind.CONSTRUCTED:
ConstructedConstantValue constant = value;
writeDartType(constant.type);
- writeMemberMap(constant.fields, writeConstant);
+ writeMemberMap(constant.fields,
+ (MemberEntity member, ConstantValue value) => writeConstant(value));
break;
case ConstantValueKind.TYPE:
TypeConstantValue constant = value;
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index a2fa583..a69e834 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -22,6 +22,9 @@
Map<Type, IndexedSource> _generalCaches = {};
+ ir.Member _currentMemberContext;
+ _MemberData _currentMemberData;
+
AbstractDataSource({this.useDataKinds: false}) {
_stringIndex = new IndexedSource<String>(this);
_uriIndex = new IndexedSource<Uri>(this);
@@ -92,6 +95,24 @@
}
@override
+ T inMemberContext<T>(ir.Member context, T f()) {
+ ir.Member oldMemberContext = _currentMemberContext;
+ _MemberData oldMemberData = _currentMemberData;
+ _currentMemberContext = context;
+ _currentMemberData = null;
+ T result = f();
+ _currentMemberData = oldMemberData;
+ _currentMemberContext = oldMemberContext;
+ return result;
+ }
+
+ _MemberData get currentMemberData {
+ assert(_currentMemberContext != null,
+ "DataSink has no current member context.");
+ return _currentMemberData ??= _getMemberData(_currentMemberContext);
+ }
+
+ @override
E readCached<E>(E f()) {
IndexedSource source = _generalCaches[E] ??= new IndexedSource<E>(this);
return source.read(f);
@@ -322,11 +343,11 @@
case MemberContextKind.cls:
_ClassData cls = _readClassData();
String name = _readString();
- return cls.lookupMember(name);
+ return cls.lookupMemberDataByName(name);
case MemberContextKind.library:
_LibraryData library = _readLibraryData();
String name = _readString();
- return library.lookupMember(name);
+ return library.lookupMemberDataByName(name);
}
throw new UnsupportedError("Unsupported _MemberKind $kind");
}
@@ -340,7 +361,7 @@
_ClassData _readClassData() {
_LibraryData library = _readLibraryData();
String name = _readString();
- return library.lookupClass(name);
+ return library.lookupClassByName(name);
}
@override
@@ -419,7 +440,64 @@
@override
ir.TreeNode readTreeNode() {
_checkDataKind(DataKind.treeNode);
- return _readTreeNode();
+ return _readTreeNode(null);
+ }
+
+ _MemberData _getMemberData(ir.Member node) {
+ _LibraryData libraryData =
+ componentLookup.getLibraryDataByUri(node.enclosingLibrary.importUri);
+ if (node.enclosingClass != null) {
+ _ClassData classData = libraryData.lookupClassByNode(node.enclosingClass);
+ return classData.lookupMemberDataByNode(node);
+ } else {
+ return libraryData.lookupMemberDataByNode(node);
+ }
+ }
+
+ @override
+ ir.TreeNode readTreeNodeInContext() {
+ return readTreeNodeInContextInternal(currentMemberData);
+ }
+
+ ir.TreeNode readTreeNodeInContextInternal(_MemberData memberData) {
+ _checkDataKind(DataKind.treeNode);
+ return _readTreeNode(memberData);
+ }
+
+ @override
+ ir.TreeNode readTreeNodeOrNullInContext() {
+ bool hasValue = readBool();
+ if (hasValue) {
+ return readTreeNodeInContextInternal(currentMemberData);
+ }
+ return null;
+ }
+
+ @override
+ List<E> readTreeNodesInContext<E extends ir.TreeNode>(
+ {bool emptyAsNull: false}) {
+ int count = readInt();
+ if (count == 0 && emptyAsNull) return null;
+ List<E> list = new List<E>(count);
+ for (int i = 0; i < count; i++) {
+ ir.TreeNode node = readTreeNodeInContextInternal(currentMemberData);
+ list[i] = node;
+ }
+ return list;
+ }
+
+ @override
+ Map<K, V> readTreeNodeMapInContext<K extends ir.TreeNode, V>(V f(),
+ {bool emptyAsNull: false}) {
+ int count = readInt();
+ if (count == 0 && emptyAsNull) return null;
+ Map<K, V> map = {};
+ for (int i = 0; i < count; i++) {
+ ir.TreeNode node = readTreeNodeInContextInternal(currentMemberData);
+ V value = f();
+ map[node] = value;
+ }
+ return map;
}
@override
@@ -493,7 +571,8 @@
case ConstantValueKind.CONSTRUCTED:
InterfaceType type = readDartType();
Map<FieldEntity, ConstantValue> fields =
- readMemberMap<FieldEntity, ConstantValue>(() => readConstant());
+ readMemberMap<FieldEntity, ConstantValue>(
+ (MemberEntity member) => readConstant());
return new ConstructedConstantValue(type, fields);
case ConstantValueKind.TYPE:
DartType representedType = readDartType();
@@ -524,7 +603,7 @@
throw new UnsupportedError("Unexpexted constant value kind ${kind}.");
}
- ir.TreeNode _readTreeNode() {
+ ir.TreeNode _readTreeNode(_MemberData memberData) {
_TreeNodeKind kind = _readEnumInternal(_TreeNodeKind.values);
switch (kind) {
case _TreeNodeKind.cls:
@@ -532,32 +611,34 @@
case _TreeNodeKind.member:
return _readMemberData().node;
case _TreeNodeKind.functionDeclarationVariable:
- ir.FunctionDeclaration functionDeclaration = _readTreeNode();
+ ir.FunctionDeclaration functionDeclaration = _readTreeNode(memberData);
return functionDeclaration.variable;
case _TreeNodeKind.functionNode:
- return _readFunctionNode();
+ return _readFunctionNode(memberData);
case _TreeNodeKind.typeParameter:
- return _readTypeParameter();
+ return _readTypeParameter(memberData);
case _TreeNodeKind.constant:
// TODO(johnniwinther): Support serialization within a member context
// and use this to temporarily cache constant node indices.
- ir.ConstantExpression expression = _readTreeNode();
+ ir.ConstantExpression expression = _readTreeNode(memberData);
_ConstantNodeIndexerVisitor indexer = new _ConstantNodeIndexerVisitor();
expression.constant.accept(indexer);
ir.Constant constant = indexer.getConstant(_readIntInternal());
return new ConstantReference(expression, constant);
case _TreeNodeKind.node:
- _MemberData data = _readMemberData();
+ if (memberData == null) {
+ memberData = _readMemberData();
+ }
int index = _readIntInternal();
- ir.TreeNode treeNode = data.getTreeNodeByIndex(index);
+ ir.TreeNode treeNode = memberData.getTreeNodeByIndex(index);
assert(treeNode != null,
- "No TreeNode found for index $index in ${data.node}.$_errorContext");
+ "No TreeNode found for index $index in ${memberData.node}.$_errorContext");
return treeNode;
}
throw new UnsupportedError("Unexpected _TreeNodeKind $kind");
}
- ir.FunctionNode _readFunctionNode() {
+ ir.FunctionNode _readFunctionNode(_MemberData memberData) {
_FunctionNodeKind kind = _readEnumInternal(_FunctionNodeKind.values);
switch (kind) {
case _FunctionNodeKind.procedure:
@@ -567,10 +648,10 @@
ir.Constructor constructor = _readMemberData().node;
return constructor.function;
case _FunctionNodeKind.functionExpression:
- ir.FunctionExpression functionExpression = _readTreeNode();
+ ir.FunctionExpression functionExpression = _readTreeNode(memberData);
return functionExpression.function;
case _FunctionNodeKind.functionDeclaration:
- ir.FunctionDeclaration functionDeclaration = _readTreeNode();
+ ir.FunctionDeclaration functionDeclaration = _readTreeNode(memberData);
return functionDeclaration.function;
}
throw new UnsupportedError("Unexpected _FunctionNodeKind $kind");
@@ -579,17 +660,17 @@
@override
ir.TypeParameter readTypeParameterNode() {
_checkDataKind(DataKind.typeParameterNode);
- return _readTypeParameter();
+ return _readTypeParameter(null);
}
- ir.TypeParameter _readTypeParameter() {
+ ir.TypeParameter _readTypeParameter(_MemberData memberData) {
_TypeParameterKind kind = _readEnumInternal(_TypeParameterKind.values);
switch (kind) {
case _TypeParameterKind.cls:
ir.Class cls = _readClassData().node;
return cls.typeParameters[_readIntInternal()];
case _TypeParameterKind.functionNode:
- ir.FunctionNode functionNode = _readFunctionNode();
+ ir.FunctionNode functionNode = _readFunctionNode(memberData);
return functionNode.typeParameters[_readIntInternal()];
}
throw new UnsupportedError("Unexpected _TypeParameterKind kind $kind");
diff --git a/pkg/compiler/lib/src/serialization/member_data.dart b/pkg/compiler/lib/src/serialization/member_data.dart
index f088210..867a271 100644
--- a/pkg/compiler/lib/src/serialization/member_data.dart
+++ b/pkg/compiler/lib/src/serialization/member_data.dart
@@ -55,27 +55,46 @@
final ir.Library node;
/// Cache of [_ClassData] for classes in this library.
- Map<String, _ClassData> _classes;
+ Map<String, _ClassData> _classesByName;
+ Map<ir.Class, _ClassData> _classesByNode;
/// Cache of [ir.Typedef] nodes for typedefs in this library.
Map<String, ir.Typedef> _typedefs;
/// Cache of [_MemberData] for members in this library.
- Map<String, _MemberData> _members;
+ Map<String, _MemberData> _membersByName;
+ Map<ir.Member, _MemberData> _membersByNode;
_LibraryData(this.node);
- /// Returns the [_ClassData] for the class [name] in this library.
- _ClassData lookupClass(String name) {
- if (_classes == null) {
- _classes = {};
+ void _ensureClasses() {
+ if (_classesByName == null) {
+ _classesByName = {};
+ _classesByNode = {};
for (ir.Class cls in node.classes) {
- assert(!_classes.containsKey(cls.name),
- "Duplicate class '${cls.name}' in $_classes trying to add $cls.");
- _classes[cls.name] = new _ClassData(cls);
+ assert(
+ !_classesByName.containsKey(cls.name),
+ "Duplicate class '${cls.name}' in $_classesByName "
+ "trying to add $cls.");
+ assert(
+ !_classesByNode.containsKey(cls),
+ "Duplicate class '${cls.name}' in $_classesByNode "
+ "trying to add $cls.");
+ _classesByNode[cls] = _classesByName[cls.name] = new _ClassData(cls);
}
}
- return _classes[name];
+ }
+
+ /// Returns the [_ClassData] for the class [name] in this library.
+ _ClassData lookupClassByName(String name) {
+ _ensureClasses();
+ return _classesByName[name];
+ }
+
+ /// Returns the [_ClassData] for the class [node] in this library.
+ _ClassData lookupClassByNode(ir.Class node) {
+ _ensureClasses();
+ return _classesByNode[node];
}
ir.Typedef lookupTypedef(String name) {
@@ -92,20 +111,37 @@
return _typedefs[name];
}
- /// Returns the [_MemberData] for the member uniquely identified by [name] in
- /// this library.
- _MemberData lookupMember(String name) {
- if (_members == null) {
- _members = {};
+ void _ensureMembers() {
+ if (_membersByName == null) {
+ _membersByName = {};
+ _membersByNode = {};
for (ir.Member member in node.members) {
String name = _computeMemberName(member);
if (name == null) continue;
- assert(!_members.containsKey(name),
- "Duplicate member '$name' in $_members trying to add $member.");
- _members[name] = new _MemberData(member);
+ assert(
+ !_membersByName.containsKey(name),
+ "Duplicate member '$name' in $_membersByName "
+ "trying to add $member.");
+ assert(
+ !_membersByNode.containsKey(member),
+ "Duplicate member '$name' in $_membersByNode "
+ "trying to add $member.");
+ _membersByNode[member] = _membersByName[name] = new _MemberData(member);
}
}
- return _members[name];
+ }
+
+ /// Returns the [_MemberData] for the member uniquely identified by [name] in
+ /// this library.
+ _MemberData lookupMemberDataByName(String name) {
+ _ensureMembers();
+ return _membersByName[name];
+ }
+
+ /// Returns the [_MemberData] for the member [node] in this library.
+ _MemberData lookupMemberDataByNode(ir.Member node) {
+ _ensureMembers();
+ return _membersByNode[node];
}
@override
@@ -118,24 +154,42 @@
final ir.Class node;
/// Cache of [_MemberData] for members in this class.
- Map<String, _MemberData> _members;
+ Map<String, _MemberData> _membersByName;
+ Map<ir.Member, _MemberData> _membersByNode;
_ClassData(this.node);
- /// Returns the [_MemberData] for the member uniquely identified by [name] in
- /// this class.
- _MemberData lookupMember(String name) {
- if (_members == null) {
- _members = {};
+ void _ensureMembers() {
+ if (_membersByName == null) {
+ _membersByName = {};
+ _membersByNode = {};
for (ir.Member member in node.members) {
String name = _computeMemberName(member);
if (name == null) continue;
- assert(!_members.containsKey(name),
- "Duplicate member '$name' in $_members trying to add $member.");
- _members[name] = new _MemberData(member);
+ assert(
+ !_membersByName.containsKey(name),
+ "Duplicate member '$name' in $_membersByName "
+ "trying to add $member.");
+ assert(
+ !_membersByNode.containsKey(member),
+ "Duplicate member '$name' in $_membersByNode "
+ "trying to add $member.");
+ _membersByNode[member] = _membersByName[name] = new _MemberData(member);
}
}
- return _members[name];
+ }
+
+ /// Returns the [_MemberData] for the member uniquely identified by [name] in
+ /// this class.
+ _MemberData lookupMemberDataByName(String name) {
+ _ensureMembers();
+ return _membersByName[name];
+ }
+
+ /// Returns the [_MemberData] for the member [node] in this class.
+ _MemberData lookupMemberDataByNode(ir.Member node) {
+ _ensureMembers();
+ return _membersByNode[node];
}
@override
diff --git a/pkg/compiler/lib/src/serialization/mixins.dart b/pkg/compiler/lib/src/serialization/mixins.dart
index 2de3e8a..c65a05c 100644
--- a/pkg/compiler/lib/src/serialization/mixins.dart
+++ b/pkg/compiler/lib/src/serialization/mixins.dart
@@ -142,14 +142,14 @@
}
@override
- Map<K, V> readMemberMap<K extends MemberEntity, V>(V f(),
+ Map<K, V> readMemberMap<K extends MemberEntity, V>(V f(MemberEntity member),
{bool emptyAsNull: false}) {
int count = readInt();
if (count == 0 && emptyAsNull) return null;
Map<K, V> map = {};
for (int i = 0; i < count; i++) {
MemberEntity member = readMember();
- V value = f();
+ V value = f(member);
map[member] = value;
}
return map;
@@ -516,7 +516,8 @@
}
@override
- void writeMemberMap<V>(Map<MemberEntity, V> map, void f(V value),
+ void writeMemberMap<V>(
+ Map<MemberEntity, V> map, void f(MemberEntity member, V value),
{bool allowNull: false}) {
if (map == null) {
assert(allowNull);
@@ -525,7 +526,7 @@
writeInt(map.length);
map.forEach((MemberEntity member, V value) {
writeMember(member);
- f(value);
+ f(member, value);
});
}
}
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index 92e6ad0..425f6d2 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -187,6 +187,35 @@
void writeTreeNodeMap<V>(Map<ir.TreeNode, V> map, void f(V value),
{bool allowNull: false});
+ /// Writes a reference to the kernel tree node [value] in the known [context]
+ /// to this data sink.
+ void writeTreeNodeInContext(ir.TreeNode value);
+
+ /// Writes a reference to the potentially `null` kernel tree node [value] in
+ /// the known [context] to this data sink.
+ ///
+ /// This is a convenience method to be used together with
+ /// [DataSource.readTreeNodeOrNullInContext].
+ void writeTreeNodeOrNullInContext(ir.TreeNode value);
+
+ /// Writes references to the kernel tree node [values] in the known [context]
+ /// to this data sink. If [allowNull] is `true`, [values] is allowed to be
+ /// `null`.
+ ///
+ /// This is a convenience method to be used together with
+ /// [DataSource.readTreeNodesInContext].
+ void writeTreeNodesInContext(Iterable<ir.TreeNode> values,
+ {bool allowNull: false});
+
+ /// Writes the [map] from references to kernel tree nodes to [V] values in the
+ /// known [context] to this data sink, calling [f] to write each value to the
+ /// data sink. If [allowNull] is `true`, [map] is allowed to be `null`.
+ ///
+ /// This is a convenience method to be used together with
+ /// [DataSource.readTreeNodeMapInContext].
+ void writeTreeNodeMapInContext<V>(Map<ir.TreeNode, V> map, void f(V value),
+ {bool allowNull: false});
+
/// Writes a reference to the kernel type parameter node [value] to this data
/// sink.
void writeTypeParameterNode(ir.TypeParameter value);
@@ -297,7 +326,8 @@
///
/// This is a convenience method to be used together with
/// [DataSource.readMemberMap].
- void writeMemberMap<V>(Map<MemberEntity, V> map, void f(V value),
+ void writeMemberMap<V>(
+ Map<MemberEntity, V> map, void f(MemberEntity member, V value),
{bool allowNull: false});
/// Writes a reference to the local [value] to this data sink.
@@ -406,6 +436,11 @@
/// Register a [CodegenWriter] with this data sink to support serialization
/// of codegen only data.
void registerCodegenWriter(CodegenWriter writer);
+
+ /// Invoke [f] in the context of [member]. This sets up support for
+ /// serialization of `ir.TreeNode`s using the `writeTreeNode*InContext`
+ /// methods.
+ void inMemberContext(ir.Member member, void f());
}
/// Interface for deserialization.
@@ -446,6 +481,11 @@
/// for deserialization of codegen only data.
void deregisterCodegenReader(CodegenReader reader);
+ /// Invoke [f] in the context of [member]. This sets up support for
+ /// deserialization of `ir.TreeNode`s using the `readTreeNode*InContext`
+ /// methods.
+ T inMemberContext<T>(ir.Member member, T f());
+
/// Reads a reference to an [E] value from this data source. If the value has
/// not yet been deserialized, [f] is called to deserialize the value itself.
E readCached<E>(E f());
@@ -577,6 +617,33 @@
Map<K, V> readTreeNodeMap<K extends ir.TreeNode, V>(V f(),
{bool emptyAsNull: false});
+ /// Reads a reference to a kernel tree node in the known [context] from this
+ /// data source.
+ ir.TreeNode readTreeNodeInContext();
+
+ /// Reads a reference to a potentially `null` kernel tree node in the known
+ /// [context] from this data source.
+ ir.TreeNode readTreeNodeOrNullInContext();
+
+ /// Reads a list of references to kernel tree nodes in the known [context]
+ /// from this data source. If [emptyAsNull] is `true`, `null` is returned
+ /// instead of an empty list.
+ ///
+ /// This is a convenience method to be used together with
+ /// [DataSink.writeTreeNodesInContext].
+ List<E> readTreeNodesInContext<E extends ir.TreeNode>(
+ {bool emptyAsNull: false});
+
+ /// Reads a map from kernel tree nodes to [V] values in the known [context]
+ /// from this data source, calling [f] to read each value from the data
+ /// source. If [emptyAsNull] is `true`, `null` is returned instead of an empty
+ /// map.
+ ///
+ /// This is a convenience method to be used together with
+ /// [DataSink.writeTreeNodeMapInContext].
+ Map<K, V> readTreeNodeMapInContext<K extends ir.TreeNode, V>(V f(),
+ {bool emptyAsNull: false});
+
/// Reads a reference to a kernel type parameter node from this data source.
ir.TypeParameter readTypeParameterNode();
@@ -668,7 +735,7 @@
///
/// This is a convenience method to be used together with
/// [DataSink.writeMemberMap].
- Map<K, V> readMemberMap<K extends MemberEntity, V>(V f(),
+ Map<K, V> readMemberMap<K extends MemberEntity, V>(V f(MemberEntity member),
{bool emptyAsNull: false});
/// Reads a reference to a local from this data source.
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 61771d5..f9affee 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -29,7 +29,7 @@
InferredData inferredData = results.inferredData;
closedWorld.writeToDataSink(sink);
inferredData.writeToDataSink(sink);
- results.writeToDataSink(sink);
+ results.writeToDataSink(sink, closedWorld.elementMap);
sink.close();
}
@@ -45,7 +45,7 @@
InferredData newInferredData =
new InferredData.readFromDataSource(source, newClosedWorld);
return new GlobalTypeInferenceResults.readFromDataSource(
- source, newClosedWorld, newInferredData);
+ source, newClosedWorld.elementMap, newClosedWorld, newInferredData);
}
class SerializationTask extends CompilerTask {
@@ -134,7 +134,9 @@
sink.registerEntityWriter(entityWriter);
sink.registerCodegenWriter(new CodegenWriterImpl(closedWorld));
sink.writeMemberMap(
- results, (CodegenResult result) => result.writeToDataSink(sink));
+ results,
+ (MemberEntity member, CodegenResult result) =>
+ result.writeToDataSink(sink));
sink.close();
});
}
@@ -155,7 +157,7 @@
DataSource source = new BinarySourceImpl(dataInput.data);
backendStrategy.prepareCodegenReader(source);
Map<MemberEntity, CodegenResult> codegenResults =
- source.readMemberMap(() {
+ source.readMemberMap((MemberEntity member) {
List<ModularName> modularNames = [];
List<ModularExpression> modularExpressions = [];
CodegenReader reader = new CodegenReaderImpl(