Reland [dart2js] Remove GlobalsLocalsMap from JClosedWorld
The removes the GlobalsLocalsMap from JClosedWorld and instead includes
it as a part of GlobalInferenceResults.
Previously landed in https://dart-review.googlesource.com/c/sdk/+/181620
but reverted.
Change-Id: I384b21bf285009c82ca9ec8740443cda0a6fa493
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/183001
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/backend_strategy.dart b/pkg/compiler/lib/src/backend_strategy.dart
index b5307e1..92966bc 100644
--- a/pkg/compiler/lib/src/backend_strategy.dart
+++ b/pkg/compiler/lib/src/backend_strategy.dart
@@ -16,6 +16,7 @@
import 'js_backend/enqueuer.dart';
import 'js_backend/inferred_data.dart';
import 'js_emitter/code_emitter_task.dart';
+import 'js_model/locals.dart';
import 'serialization/serialization.dart';
import 'ssa/ssa.dart';
import 'universe/codegen_world_builder.dart';
@@ -65,8 +66,8 @@
SourceSpan spanFromSpannable(Spannable spannable, Entity currentElement);
/// Creates the [TypesInferrer] used by this strategy.
- TypesInferrer createTypesInferrer(
- JClosedWorld closedWorld, InferredDataBuilder inferredDataBuilder);
+ TypesInferrer createTypesInferrer(JClosedWorld closedWorld,
+ GlobalLocalsMap globalLocalsMap, InferredDataBuilder inferredDataBuilder);
/// Calls [f] for every member that needs to be serialized for modular code
/// generation and returns an [EntityWriter] for encoding these members in
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 2d0efa6..6f26060 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -35,6 +35,14 @@
/// Accessor to the information about scopes that closures capture. Used by
/// the SSA builder.
CapturedScope getCapturedScope(MemberEntity entity);
+
+ /// If [entity] is a closure call method or closure signature method, the
+ /// original enclosing member is returned. Otherwise [entity] is returned.
+ ///
+ /// A member and its nested closure share the underlying AST, we need to
+ /// ensure that locals are shared between them. We therefore store the
+ /// locals in the global locals map using the enclosing member as key.
+ MemberEntity getEnclosingMember(MemberEntity entity);
}
/// Enum used for identifying [ScopeInfo] subclasses in serialization.
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 6faa855..e921146 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -39,6 +39,7 @@
import 'js_backend/inferred_data.dart';
import 'js_model/js_strategy.dart';
import 'js_model/js_world.dart';
+import 'js_model/locals.dart';
import 'kernel/kernel_strategy.dart';
import 'kernel/loader.dart' show KernelLoaderTask, KernelResult;
import 'null_compiler_output.dart' show NullCompilerOutput;
@@ -401,10 +402,12 @@
JClosedWorld closedWorld) {
FunctionEntity mainFunction = closedWorld.elementEnvironment.mainFunction;
reporter.log('Performing global type inference');
+ GlobalLocalsMap globalLocalsMap =
+ new GlobalLocalsMap(closedWorld.closureDataLookup.getEnclosingMember);
InferredDataBuilder inferredDataBuilder =
new InferredDataBuilderImpl(closedWorld.annotationsData);
return globalInference.runGlobalTypeInference(
- mainFunction, closedWorld, inferredDataBuilder);
+ mainFunction, closedWorld, globalLocalsMap, inferredDataBuilder);
}
void runCodegenEnqueuer(CodegenResults codegenResults) {
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 691151c..882895c 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -271,7 +271,7 @@
List<String> inferredParameterTypes = <String>[];
closedWorld.elementEnvironment.forEachParameterAsLocal(
- closedWorld.globalLocalsMap, function, (parameter) {
+ _globalInferenceResults.globalLocalsMap, function, (parameter) {
inferredParameterTypes.add('${_resultOfParameter(parameter)}');
});
int parameterIndex = 0;
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index 129b30b..39c1a06 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -64,6 +64,7 @@
final TypeSystem types;
final Map<ir.TreeNode, TypeInformation> concreteTypes = {};
+ final GlobalLocalsMap globalLocalsMap;
final InferredDataBuilder inferredDataBuilder;
final FunctionEntity mainElement;
@@ -114,9 +115,10 @@
this._compilerOutput,
this.closedWorld,
this.mainElement,
+ this.globalLocalsMap,
this.inferredDataBuilder)
- : this.types = new TypeSystem(
- closedWorld, new KernelTypeSystemStrategy(closedWorld));
+ : this.types = new TypeSystem(closedWorld,
+ new KernelTypeSystemStrategy(closedWorld, globalLocalsMap));
/// Applies [f] to all elements in the universe that match [selector] and
/// [mask]. If [f] returns false, aborts the iteration.
@@ -634,7 +636,7 @@
this,
member,
body,
- closedWorld.globalLocalsMap.getLocalsMap(member),
+ globalLocalsMap.getLocalsMap(member),
closedWorld.elementMap.getStaticTypeProvider(member));
return visitor.run();
}
@@ -1224,8 +1226,9 @@
class KernelTypeSystemStrategy implements TypeSystemStrategy {
final JsClosedWorld _closedWorld;
+ final GlobalLocalsMap _globalLocalsMap;
- KernelTypeSystemStrategy(this._closedWorld);
+ KernelTypeSystemStrategy(this._closedWorld, this._globalLocalsMap);
JElementEnvironment get _elementEnvironment =>
_closedWorld.elementEnvironment;
@@ -1252,8 +1255,8 @@
@override
void forEachParameter(FunctionEntity function, void f(Local parameter)) {
forEachOrderedParameterAsLocal(
- _closedWorld.globalLocalsMap, _closedWorld.elementMap, function,
- (Local parameter, {bool isElided}) {
+ _globalLocalsMap, _closedWorld.elementMap, function, (Local parameter,
+ {bool isElided}) {
f(parameter);
});
}
@@ -1264,8 +1267,7 @@
covariant JLocal parameter,
TypeSystem types) {
MemberEntity context = parameter.memberContext;
- KernelToLocalsMap localsMap =
- _closedWorld.globalLocalsMap.getLocalsMap(context);
+ KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(context);
ir.FunctionNode functionNode =
localsMap.getFunctionNodeForParameter(parameter);
DartType type = localsMap.getLocalType(_closedWorld.elementMap, parameter);
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index 7ab25ce..f770d9b 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -13,6 +13,7 @@
import '../elements/entities.dart';
import '../js_backend/inferred_data.dart';
import '../js_model/elements.dart' show JClosureCallMethod;
+import '../js_model/locals.dart';
import '../world.dart';
import 'abstract_value_domain.dart';
import 'inferrer_engine.dart';
@@ -53,11 +54,12 @@
final JClosedWorld closedWorld;
final Compiler _compiler;
+ final GlobalLocalsMap _globalLocalsMap;
final InferredDataBuilder _inferredDataBuilder;
Metrics /*?*/ _metrics;
- TypeGraphInferrer(
- this._compiler, this.closedWorld, this._inferredDataBuilder);
+ TypeGraphInferrer(this._compiler, this.closedWorld, this._globalLocalsMap,
+ this._inferredDataBuilder);
String get name => 'Graph inferrer';
@@ -82,6 +84,7 @@
_compiler.outputProvider,
closedWorld,
main,
+ _globalLocalsMap,
_inferredDataBuilder);
}
@@ -134,8 +137,7 @@
if (member is JClosureCallMethod) {
ClosureRepresentationInfo info =
closedWorld.closureDataLookup.getScopeInfo(member);
- info.forEachFreeVariable(
- closedWorld.globalLocalsMap.getLocalsMap(member),
+ info.forEachFreeVariable(_globalLocalsMap.getLocalsMap(member),
(Local from, FieldEntity to) {
freeVariables.add(to);
});
@@ -169,6 +171,7 @@
GlobalTypeInferenceResults results = new GlobalTypeInferenceResultsImpl(
closedWorld,
+ _globalLocalsMap,
_inferredDataBuilder.close(closedWorld),
memberResults,
parameterResults,
diff --git a/pkg/compiler/lib/src/inferrer/types.dart b/pkg/compiler/lib/src/inferrer/types.dart
index 66d551c..2345d53 100644
--- a/pkg/compiler/lib/src/inferrer/types.dart
+++ b/pkg/compiler/lib/src/inferrer/types.dart
@@ -13,6 +13,8 @@
import '../elements/entities.dart';
import '../js_backend/inferred_data.dart';
import '../js_model/element_map.dart';
+import '../js_model/js_world.dart';
+import '../js_model/locals.dart';
import '../inferrer/type_graph_inferrer.dart' show TypeGraphInferrer;
import '../serialization/serialization.dart';
import '../universe/selector.dart' show Selector;
@@ -111,13 +113,15 @@
DataSource source,
JsToElementMap elementMap,
JClosedWorld closedWorld,
+ GlobalLocalsMap globalLocalsMap,
InferredData inferredData) {
bool isTrivial = source.readBool();
if (isTrivial) {
- return new TrivialGlobalTypeInferenceResults(closedWorld);
+ return new TrivialGlobalTypeInferenceResults(
+ closedWorld, globalLocalsMap);
}
return new GlobalTypeInferenceResultsImpl.readFromDataSource(
- source, elementMap, closedWorld, inferredData);
+ source, elementMap, closedWorld, globalLocalsMap, inferredData);
}
/// Serializes this [GlobalTypeInferenceResults] to [sink].
@@ -125,6 +129,8 @@
JClosedWorld get closedWorld;
+ GlobalLocalsMap get globalLocalsMap;
+
InferredData get inferredData;
GlobalTypeInferenceMemberResult resultOfMember(MemberEntity member);
@@ -171,16 +177,20 @@
Metrics get metrics => _metrics;
/// Runs the global type-inference algorithm once.
- GlobalTypeInferenceResults runGlobalTypeInference(FunctionEntity mainElement,
- JClosedWorld closedWorld, InferredDataBuilder inferredDataBuilder) {
+ GlobalTypeInferenceResults runGlobalTypeInference(
+ FunctionEntity mainElement,
+ JClosedWorld closedWorld,
+ GlobalLocalsMap globalLocalsMap,
+ InferredDataBuilder inferredDataBuilder) {
return measure(() {
GlobalTypeInferenceResults results;
if (compiler.disableTypeInference) {
- results = new TrivialGlobalTypeInferenceResults(closedWorld);
+ results =
+ new TrivialGlobalTypeInferenceResults(closedWorld, globalLocalsMap);
_metrics = Metrics.none();
} else {
- typesInferrerInternal ??= compiler.backendStrategy
- .createTypesInferrer(closedWorld, inferredDataBuilder);
+ typesInferrerInternal ??= compiler.backendStrategy.createTypesInferrer(
+ closedWorld, globalLocalsMap, inferredDataBuilder);
results = typesInferrerInternal.analyzeMain(mainElement);
_metrics = typesInferrerInternal.metrics;
}
@@ -201,6 +211,8 @@
@override
final JClosedWorld closedWorld;
@override
+ final GlobalLocalsMap globalLocalsMap;
+ @override
final InferredData inferredData;
final GlobalTypeInferenceMemberResult _deadFieldResult;
final GlobalTypeInferenceMemberResult _deadMethodResult;
@@ -214,6 +226,7 @@
GlobalTypeInferenceResultsImpl(
this.closedWorld,
+ this.globalLocalsMap,
this.inferredData,
this.memberResults,
this.parameterResults,
@@ -230,7 +243,10 @@
DataSource source,
JsToElementMap elementMap,
JClosedWorld closedWorld,
+ GlobalLocalsMap globalLocalsMap,
InferredData inferredData) {
+ source.registerLocalLookup(new LocalLookupImpl(globalLocalsMap));
+
source.begin(tag);
Map<MemberEntity, GlobalTypeInferenceMemberResult> memberResults =
source.readMemberMap((MemberEntity member) =>
@@ -250,6 +266,7 @@
source.end(tag);
return new GlobalTypeInferenceResultsImpl(
closedWorld,
+ globalLocalsMap,
inferredData,
memberResults,
parameterResults,
@@ -472,8 +489,10 @@
final AbstractValue _trivialParameterResult;
@override
final InferredData inferredData = new TrivialInferredData();
+ @override
+ final GlobalLocalsMap globalLocalsMap;
- TrivialGlobalTypeInferenceResults(this.closedWorld)
+ TrivialGlobalTypeInferenceResults(this.closedWorld, this.globalLocalsMap)
: _trivialMemberResult = new TrivialGlobalTypeInferenceMemberResult(
closedWorld.abstractValueDomain.dynamicType),
_trivialParameterResult = closedWorld.abstractValueDomain.dynamicType;
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index 8f71fb8..cfdee0b 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -21,7 +21,6 @@
import '../universe/selector.dart';
import 'elements.dart';
import 'js_world_builder.dart' show JsClosedWorldBuilder;
-import 'locals.dart';
class ClosureDataImpl implements ClosureData {
/// Tag used for identifying serialized [ClosureData] objects in a
@@ -40,8 +39,15 @@
final Map<ir.LocalFunction, ClosureRepresentationInfo>
_localClosureRepresentationMap;
- ClosureDataImpl(this._elementMap, this._scopeMap, this._capturedScopesMap,
- this._capturedScopeForSignatureMap, this._localClosureRepresentationMap);
+ final Map<MemberEntity, MemberEntity> _enclosingMembers;
+
+ ClosureDataImpl(
+ this._elementMap,
+ this._scopeMap,
+ this._capturedScopesMap,
+ this._capturedScopeForSignatureMap,
+ this._localClosureRepresentationMap,
+ this._enclosingMembers);
/// Deserializes a [ClosureData] object from [source].
factory ClosureDataImpl.readFromDataSource(
@@ -58,9 +64,16 @@
Map<ir.LocalFunction, ClosureRepresentationInfo>
localClosureRepresentationMap = source.readTreeNodeMap(
() => new ClosureRepresentationInfo.readFromDataSource(source));
+ Map<MemberEntity, MemberEntity> enclosingMembers =
+ source.readMemberMap((member) => source.readMember());
source.end(tag);
- return new ClosureDataImpl(elementMap, scopeMap, capturedScopesMap,
- capturedScopeForSignatureMap, localClosureRepresentationMap);
+ return new ClosureDataImpl(
+ elementMap,
+ scopeMap,
+ capturedScopesMap,
+ capturedScopeForSignatureMap,
+ localClosureRepresentationMap,
+ enclosingMembers);
}
/// Serializes this [ClosureData] to [sink].
@@ -80,6 +93,10 @@
(ClosureRepresentationInfo info) {
info.writeToDataSink(sink);
});
+ sink.writeMemberMap(_enclosingMembers,
+ (MemberEntity member, MemberEntity value) {
+ sink.writeMember(value);
+ });
sink.end(tag);
}
@@ -132,6 +149,11 @@
"Closures found for ${_localClosureRepresentationMap.keys}");
return closure;
}
+
+ @override
+ MemberEntity getEnclosingMember(MemberEntity member) {
+ return _enclosingMembers[member] ?? member;
+ }
}
/// Closure conversion code using our new Entity model. Closure conversion is
@@ -149,7 +171,6 @@
class ClosureDataBuilder {
final JsToElementMap _elementMap;
- final GlobalLocalsMap _globalLocalsMap;
final AnnotationsData _annotationsData;
/// Map of the scoping information that corresponds to a particular entity.
@@ -162,8 +183,9 @@
Map<ir.LocalFunction, ClosureRepresentationInfo>
_localClosureRepresentationMap = {};
- ClosureDataBuilder(
- this._elementMap, this._globalLocalsMap, this._annotationsData);
+ Map<MemberEntity, MemberEntity> _enclosingMembers = {};
+
+ ClosureDataBuilder(this._elementMap, this._annotationsData);
void _updateScopeBasedOnRtiNeed(KernelScopeInfo scope, ClosureRtiNeed rtiNeed,
MemberEntity outermostEntity) {
@@ -360,8 +382,13 @@
callMethods.add(closureClassInfo.callMethod);
}
});
- return new ClosureDataImpl(_elementMap, _scopeMap, _capturedScopesMap,
- _capturedScopeForSignatureMap, _localClosureRepresentationMap);
+ return new ClosureDataImpl(
+ _elementMap,
+ _scopeMap,
+ _capturedScopesMap,
+ _capturedScopeForSignatureMap,
+ _localClosureRepresentationMap,
+ _enclosingMembers);
}
/// Given what variables are captured at each point, construct closure classes
@@ -379,17 +406,15 @@
ClosureRtiNeed rtiNeed,
{bool createSignatureMethod}) {
_updateScopeBasedOnRtiNeed(info, rtiNeed, member);
- KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(member);
JsClosureClassInfo closureClassInfo = closedWorldBuilder.buildClosureClass(
member, node, member.library, boxedVariables, info,
createSignatureMethod: createSignatureMethod);
// We want the original declaration where that function is used to point
// to the correct closure class.
- _globalLocalsMap.setLocalsMap(closureClassInfo.callMethod, localsMap);
+ _enclosingMembers[closureClassInfo.callMethod] = member;
if (closureClassInfo.signatureMethod != null) {
- _globalLocalsMap.setLocalsMap(
- closureClassInfo.signatureMethod, localsMap);
+ _enclosingMembers[closureClassInfo.signatureMethod] = member;
}
if (node.parent is ir.Member) {
assert(_elementMap.getMember(node.parent) == member);
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index bb9ed2b..d432e33 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -169,12 +169,10 @@
strategy.elementMap,
closedWorld.liveMemberUsage,
closedWorld.annotationsData);
- GlobalLocalsMap _globalLocalsMap = new GlobalLocalsMap();
- ClosureDataBuilder closureDataBuilder = new ClosureDataBuilder(
- _elementMap, _globalLocalsMap, closedWorld.annotationsData);
+ ClosureDataBuilder closureDataBuilder =
+ new ClosureDataBuilder(_elementMap, closedWorld.annotationsData);
JsClosedWorldBuilder closedWorldBuilder = new JsClosedWorldBuilder(
_elementMap,
- _globalLocalsMap,
closureDataBuilder,
_compiler.options,
_compiler.abstractValueStrategy);
@@ -383,8 +381,11 @@
@override
TypesInferrer createTypesInferrer(
- JClosedWorld closedWorld, InferredDataBuilder inferredDataBuilder) {
- return new TypeGraphInferrer(_compiler, closedWorld, inferredDataBuilder);
+ JClosedWorld closedWorld,
+ GlobalLocalsMap globalLocalsMap,
+ InferredDataBuilder inferredDataBuilder) {
+ return new TypeGraphInferrer(
+ _compiler, closedWorld, globalLocalsMap, inferredDataBuilder);
}
@override
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index 2b5263a..868ef6f 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -90,8 +90,6 @@
@override
final AnnotationsData annotationsData;
@override
- final GlobalLocalsMap globalLocalsMap;
- @override
final ClosureData closureDataLookup;
@override
final OutputUnitData outputUnitData;
@@ -118,7 +116,6 @@
this.classHierarchy,
AbstractValueStrategy abstractValueStrategy,
this.annotationsData,
- this.globalLocalsMap,
this.closureDataLookup,
this.outputUnitData,
this.memberAccess) {
@@ -138,9 +135,6 @@
JsKernelToElementMap elementMap =
new JsKernelToElementMap.readFromDataSource(
options, reporter, environment, component, source);
- GlobalLocalsMap globalLocalsMap =
- new GlobalLocalsMap.readFromDataSource(source);
- source.registerLocalLookup(new LocalLookupImpl(globalLocalsMap));
ClassHierarchy classHierarchy = new ClassHierarchy.readFromDataSource(
source, elementMap.commonElements);
NativeData nativeData = new NativeData.readFromDataSource(
@@ -203,7 +197,6 @@
classHierarchy,
abstractValueStrategy,
annotationsData,
- globalLocalsMap,
closureData,
outputUnitData,
memberAccess);
@@ -213,8 +206,6 @@
void writeToDataSink(DataSink sink) {
sink.begin(tag);
elementMap.writeToDataSink(sink);
- globalLocalsMap.writeToDataSink(sink);
-
classHierarchy.writeToDataSink(sink);
nativeData.writeToDataSink(sink);
interceptorData.writeToDataSink(sink);
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
index b1a80ce..f2fdbe6 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -36,20 +36,18 @@
import 'elements.dart';
import 'element_map_impl.dart';
import 'js_world.dart';
-import 'locals.dart';
class JsClosedWorldBuilder {
final JsKernelToElementMap _elementMap;
final Map<ClassEntity, ClassHierarchyNode> _classHierarchyNodes =
new ClassHierarchyNodesMap();
final Map<ClassEntity, ClassSet> _classSets = <ClassEntity, ClassSet>{};
- final GlobalLocalsMap _globalLocalsMap;
final ClosureDataBuilder _closureDataBuilder;
final CompilerOptions _options;
final AbstractValueStrategy _abstractValueStrategy;
- JsClosedWorldBuilder(this._elementMap, this._globalLocalsMap,
- this._closureDataBuilder, this._options, this._abstractValueStrategy);
+ JsClosedWorldBuilder(this._elementMap, this._closureDataBuilder,
+ this._options, this._abstractValueStrategy);
ElementEnvironment get _elementEnvironment => _elementMap.elementEnvironment;
CommonElements get _commonElements => _elementMap.commonElements;
@@ -235,7 +233,6 @@
_elementMap.commonElements, _classHierarchyNodes, _classSets),
_abstractValueStrategy,
annotationsData,
- _globalLocalsMap,
closureData,
outputUnitData,
memberAccess);
diff --git a/pkg/compiler/lib/src/js_model/locals.dart b/pkg/compiler/lib/src/js_model/locals.dart
index 0e458ed..1d5cd00 100644
--- a/pkg/compiler/lib/src/js_model/locals.dart
+++ b/pkg/compiler/lib/src/js_model/locals.dart
@@ -22,14 +22,23 @@
/// debugging data stream.
static const String tag = 'global-locals-map';
+ /// Lookup up the key used to store a LocalsMap for a member.
+ ///
+ /// While procedures are keyed by their own entity, closures use the
+ /// enclosing member as a key. This ensures that the member and all
+ /// nested closures share the same local map.
+ MemberEntity Function(MemberEntity) _localMapKeyLookup;
+
final Map<MemberEntity, KernelToLocalsMap> _localsMaps;
- GlobalLocalsMap() : _localsMaps = {};
+ GlobalLocalsMap(this._localMapKeyLookup) : _localsMaps = {};
- GlobalLocalsMap.internal(this._localsMaps);
+ GlobalLocalsMap.internal(this._localMapKeyLookup, this._localsMaps);
/// Deserializes a [GlobalLocalsMap] object from [source].
- factory GlobalLocalsMap.readFromDataSource(DataSource source) {
+ factory GlobalLocalsMap.readFromDataSource(
+ MemberEntity Function(MemberEntity) localMapKeyLookup,
+ DataSource source) {
source.begin(tag);
Map<MemberEntity, KernelToLocalsMap> _localsMaps = {};
int mapCount = source.readInt();
@@ -42,7 +51,7 @@
}
}
source.end(tag);
- return new GlobalLocalsMap.internal(_localsMaps);
+ return new GlobalLocalsMap.internal(localMapKeyLookup, _localsMaps);
}
/// Serializes this [GlobalLocalsMap] to [sink].
@@ -68,26 +77,19 @@
/// Returns the [KernelToLocalsMap] for [member].
KernelToLocalsMap getLocalsMap(MemberEntity member) {
- // If element is a ConstructorBodyEntity, its localsMap is the same as for
+ // If [member] is a closure call method or closure signature method, its
+ // localsMap is the same as for the enclosing member since the locals are
+ // derived from the same kernel AST.
+ MemberEntity key = _localMapKeyLookup(member);
+ // If [member] is a ConstructorBodyEntity, its localsMap is the same as for
// ConstructorEntity, because both of these entities came from the same
// constructor node. The entities are two separate parts because JS does not
// have the concept of an initializer list, so the constructor (initializer
// list) and the constructor body are implemented as two separate
// constructor steps.
- MemberEntity entity = member;
- if (entity is ConstructorBodyEntity) member = entity.constructor;
- return _localsMaps.putIfAbsent(
- member, () => new KernelToLocalsMapImpl(member));
- }
-
- /// Associates [localsMap] with [member].
- ///
- /// Use this for sharing maps between members that share IR nodes.
- void setLocalsMap(MemberEntity member, KernelToLocalsMap localsMap) {
- assert(member != null, "No member provided.");
- assert(!_localsMaps.containsKey(member),
- "Locals map already created for $member.");
- _localsMaps[member] = localsMap;
+ MemberEntity entity = key;
+ if (entity is ConstructorBodyEntity) key = entity.constructor;
+ return _localsMaps.putIfAbsent(key, () => new KernelToLocalsMapImpl(key));
}
}
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 707def0..3ac7e86 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -19,6 +19,7 @@
import '../js_backend/backend.dart';
import '../js_backend/inferred_data.dart';
import '../js_model/js_world.dart';
+import '../js_model/locals.dart';
import '../options.dart';
import '../util/sink_adapter.dart';
import '../world.dart';
@@ -27,8 +28,10 @@
void serializeGlobalTypeInferenceResultsToSink(
GlobalTypeInferenceResults results, DataSink sink) {
JsClosedWorld closedWorld = results.closedWorld;
+ GlobalLocalsMap globalLocalsMap = results.globalLocalsMap;
InferredData inferredData = results.inferredData;
closedWorld.writeToDataSink(sink);
+ globalLocalsMap.writeToDataSink(sink);
inferredData.writeToDataSink(sink);
results.writeToDataSink(sink, closedWorld.elementMap);
sink.close();
@@ -42,10 +45,16 @@
ir.Component component,
JsClosedWorld newClosedWorld,
DataSource source) {
+ GlobalLocalsMap newGlobalLocalsMap = GlobalLocalsMap.readFromDataSource(
+ newClosedWorld.closureDataLookup.getEnclosingMember, source);
InferredData newInferredData =
InferredData.readFromDataSource(source, newClosedWorld);
return GlobalTypeInferenceResults.readFromDataSource(
- source, newClosedWorld.elementMap, newClosedWorld, newInferredData);
+ source,
+ newClosedWorld.elementMap,
+ newClosedWorld,
+ newGlobalLocalsMap,
+ newInferredData);
}
GlobalTypeInferenceResults deserializeGlobalTypeInferenceResultsFromSource(
@@ -57,10 +66,16 @@
DataSource source) {
JsClosedWorld newClosedWorld = new JsClosedWorld.readFromDataSource(
options, reporter, environment, abstractValueStrategy, component, source);
+ GlobalLocalsMap newGlobalLocalsMap = GlobalLocalsMap.readFromDataSource(
+ newClosedWorld.closureDataLookup.getEnclosingMember, source);
InferredData newInferredData =
new InferredData.readFromDataSource(source, newClosedWorld);
return new GlobalTypeInferenceResults.readFromDataSource(
- source, newClosedWorld.elementMap, newClosedWorld, newInferredData);
+ source,
+ newClosedWorld.elementMap,
+ newClosedWorld,
+ newGlobalLocalsMap,
+ newInferredData);
}
void serializeClosedWorldToSink(JsClosedWorld closedWorld, DataSink sink) {
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index f3b714a..4bd37c8 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -34,7 +34,7 @@
import '../js_backend/native_data.dart';
import '../js_backend/runtime_types_resolution.dart';
import '../js_emitter/code_emitter_task.dart' show ModularEmitter;
-import '../js_model/locals.dart' show JumpVisitor;
+import '../js_model/locals.dart' show GlobalLocalsMap, JumpVisitor;
import '../js_model/elements.dart' show JGeneratorBody;
import '../js_model/element_map.dart';
import '../js_model/js_strategy.dart';
@@ -212,6 +212,9 @@
RuntimeTypesNeed get _rtiNeed => closedWorld.rtiNeed;
+ GlobalLocalsMap get _globalLocalsMap =>
+ globalInferenceResults.globalLocalsMap;
+
InferredData get _inferredData => globalInferenceResults.inferredData;
DartTypes get dartTypes => closedWorld.dartTypes;
@@ -408,7 +411,7 @@
_currentFrame,
member,
asyncMarker,
- closedWorld.globalLocalsMap.getLocalsMap(member),
+ _globalLocalsMap.getLocalsMap(member),
{},
new KernelToTypeInferenceMapImpl(member, globalInferenceResults),
_currentFrame != null
@@ -6030,8 +6033,7 @@
ir.Member memberContextNode = _elementMap.getMemberContextNode(function);
bool hasBox = false;
- KernelToLocalsMap localsMap =
- closedWorld.globalLocalsMap.getLocalsMap(function);
+ KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(function);
forEachOrderedParameter(_elementMap, function,
(ir.VariableDeclaration variable, {bool isElided}) {
Local local = localsMap.getLocalVariable(variable);
@@ -6198,8 +6200,7 @@
_checkTypeVariableBounds(function);
}
- KernelToLocalsMap localsMap =
- closedWorld.globalLocalsMap.getLocalsMap(function);
+ KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(function);
forEachOrderedParameter(_elementMap, function,
(ir.VariableDeclaration variable, {bool isElided}) {
Local parameter = localsMap.getLocalVariable(variable);
diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart
index e1edc64..ea01915 100644
--- a/pkg/compiler/lib/src/ssa/locals_handler.dart
+++ b/pkg/compiler/lib/src/ssa/locals_handler.dart
@@ -14,7 +14,7 @@
import '../js_backend/native_data.dart';
import '../js_backend/interceptor_data.dart';
import '../js_model/closure.dart' show JRecordField, JClosureField;
-import '../js_model/locals.dart' show JLocal;
+import '../js_model/locals.dart' show GlobalLocalsMap, JLocal;
import '../world.dart' show JClosedWorld;
import 'builder_kernel.dart';
@@ -79,6 +79,9 @@
GlobalTypeInferenceResults get _globalInferenceResults =>
builder.globalInferenceResults;
+ GlobalLocalsMap get _globalLocalsMap =>
+ _globalInferenceResults.globalLocalsMap;
+
/// Substituted type variables occurring in [type] into the context of
/// [contextClass].
DartType substInContext(DartType type) {
@@ -123,7 +126,7 @@
_scopeInfoMember = member;
if (member != null) {
_scopeInfo = _closedWorld.closureDataLookup.getScopeInfo(member);
- _localsMap = _closedWorld.globalLocalsMap.getLocalsMap(member);
+ _localsMap = _globalLocalsMap.getLocalsMap(member);
} else {
_scopeInfo = null;
_localsMap = null;
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index fc7f564..68effb3 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -26,7 +26,6 @@
import 'js_backend/native_data.dart' show NativeData;
import 'js_backend/no_such_method_registry.dart' show NoSuchMethodData;
import 'js_backend/runtime_types_resolution.dart' show RuntimeTypesNeed;
-import 'js_model/locals.dart';
import 'js_emitter/sorter.dart';
import 'universe/class_hierarchy.dart';
import 'universe/member_usage.dart';
@@ -78,7 +77,6 @@
AnnotationsData get annotationsData;
- GlobalLocalsMap get globalLocalsMap;
ClosureData get closureDataLookup;
OutputUnitData get outputUnitData;
diff --git a/pkg/compiler/test/closure/closure_test.dart b/pkg/compiler/test/closure/closure_test.dart
index f1ed2bd..231025d 100644
--- a/pkg/compiler/test/closure/closure_test.dart
+++ b/pkg/compiler/test/closure/closure_test.dart
@@ -38,7 +38,8 @@
{bool verbose: false}) {
JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
JsToElementMap elementMap = closedWorld.elementMap;
- GlobalLocalsMap localsMap = closedWorld.globalLocalsMap;
+ GlobalLocalsMap localsMap =
+ compiler.globalInference.resultsForTesting.globalLocalsMap;
ClosureData closureDataLookup = closedWorld.closureDataLookup;
MemberDefinition definition = elementMap.getMemberDefinition(member);
assert(
diff --git a/pkg/compiler/test/codegen/expect_annotations_test.dart b/pkg/compiler/test/codegen/expect_annotations_test.dart
index 9ed3517..a3df294 100644
--- a/pkg/compiler/test/codegen/expect_annotations_test.dart
+++ b/pkg/compiler/test/codegen/expect_annotations_test.dart
@@ -55,7 +55,7 @@
AbstractValue expectedReturnType,
GlobalTypeInferenceResults results) {
closedWorld.elementEnvironment.forEachParameterAsLocal(
- closedWorld.globalLocalsMap, function, (Local parameter) {
+ results.globalLocalsMap, function, (Local parameter) {
AbstractValue type = results.resultOfParameter(parameter);
Expect.equals(
expectedParameterType, simplify(type, commonMasks), "$parameter");
diff --git a/pkg/compiler/test/codegen/type_inference8_test.dart b/pkg/compiler/test/codegen/type_inference8_test.dart
index 382ef35..252f2e4 100644
--- a/pkg/compiler/test/codegen/type_inference8_test.dart
+++ b/pkg/compiler/test/codegen/type_inference8_test.dart
@@ -62,7 +62,7 @@
// the argument to 'bar' is always false
MemberEntity bar = elementEnvironment.lookupLibraryMember(
elementEnvironment.mainLibrary, 'bar');
- elementEnvironment.forEachParameterAsLocal(closedWorld.globalLocalsMap, bar,
+ elementEnvironment.forEachParameterAsLocal(results.globalLocalsMap, bar,
(barArg) {
AbstractValue barArgMask = results.resultOfParameter(barArg);
Expect.equals(falseType, barArgMask);
@@ -110,7 +110,7 @@
Expect.identical(commonMasks.boolType, mask);
MemberEntity bar = elementEnvironment.lookupLibraryMember(
elementEnvironment.mainLibrary, 'bar');
- elementEnvironment.forEachParameterAsLocal(closedWorld.globalLocalsMap, bar,
+ elementEnvironment.forEachParameterAsLocal(results.globalLocalsMap, bar,
(barArg) {
AbstractValue barArgMask = results.resultOfParameter(barArg);
// The argument to bar should have the same type as the return type of foo
diff --git a/pkg/compiler/test/inference/inference_test_helper.dart b/pkg/compiler/test/inference/inference_test_helper.dart
index fa5feb0..d049559 100644
--- a/pkg/compiler/test/inference/inference_test_helper.dart
+++ b/pkg/compiler/test/inference/inference_test_helper.dart
@@ -52,7 +52,9 @@
{bool verbose: false}) {
JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
JsToElementMap elementMap = closedWorld.elementMap;
- GlobalLocalsMap localsMap = closedWorld.globalLocalsMap;
+ GlobalTypeInferenceResults results =
+ compiler.globalInference.resultsForTesting;
+ GlobalLocalsMap localsMap = results.globalLocalsMap;
MemberDefinition definition = elementMap.getMemberDefinition(member);
new TypeMaskIrComputer(
compiler.reporter,
@@ -60,7 +62,7 @@
elementMap,
member,
localsMap.getLocalsMap(member),
- compiler.globalInference.resultsForTesting,
+ results,
closedWorld.closureDataLookup)
.run(definition.node);
}
diff --git a/pkg/compiler/test/inference/load_deferred_library_test.dart b/pkg/compiler/test/inference/load_deferred_library_test.dart
index aad3724..8c6e15e 100644
--- a/pkg/compiler/test/inference/load_deferred_library_test.dart
+++ b/pkg/compiler/test/inference/load_deferred_library_test.dart
@@ -51,8 +51,9 @@
helperLibrary, 'loadDeferredLibrary');
TypeMask typeMask;
- KernelToLocalsMap localsMap =
- closedWorld.globalLocalsMap.getLocalsMap(loadDeferredLibrary);
+ KernelToLocalsMap localsMap = compiler
+ .globalInference.resultsForTesting.globalLocalsMap
+ .getLocalsMap(loadDeferredLibrary);
MemberDefinition definition =
closedWorld.elementMap.getMemberDefinition(loadDeferredLibrary);
ir.Procedure procedure = definition.node;
diff --git a/pkg/compiler/test/jumps/jump_test.dart b/pkg/compiler/test/jumps/jump_test.dart
index 35b67d1..b848bd7 100644
--- a/pkg/compiler/test/jumps/jump_test.dart
+++ b/pkg/compiler/test/jumps/jump_test.dart
@@ -39,7 +39,8 @@
{bool verbose: false}) {
JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
JsToElementMap elementMap = closedWorld.elementMap;
- GlobalLocalsMap localsMap = closedWorld.globalLocalsMap;
+ GlobalLocalsMap localsMap =
+ compiler.globalInference.resultsForTesting.globalLocalsMap;
MemberDefinition definition = elementMap.getMemberDefinition(member);
new JumpsIrChecker(
compiler.reporter, actualMap, localsMap.getLocalsMap(member))